Building Asp.Net Core web application with Webpack and React



1. Create a New Asp.Net core application with "Empty" template.




The initial project will look like this:

                                       


2. Modify startup.cs, Add MVC service and create a default route in UseMVC service



3. Create a "controllers" folder and add a Portal Controller. (May require to restart project)


4. Create a view


If you run the web application now, it will render the MVC service and display the main.cshtml page.


Installing Webpack
==============

5. Run "npm init -y" in the command window => this will create a package.json file

6. To install webpack run the following command

      "npm install webpack --save-dev"

7. Add the following lines to the scripts tag in package.json file

 "scripts":{
    {"webpack""webpack",
     "webpack-vendor""webpack --config webpack.config.vendor.js"
}

8. Add "webpack.config.js" and "webpack.confog.vendor.js" file using Visual Studio

Webpack.config.js

const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
const autoprefixer = require('autoprefixer');
const CleanWebpackPlugin = require('clean-webpack-plugin');

let tempDir = '../../obj/WebAssess';

module.exports = (env) => {
    const isDevBuild = !(env && env.prod);

    const outputDir = (env && env.publishDir)
        ? env.publishDir
        : __dirname;

    const extractSass = new ExtractTextPlugin({
        filename: "dist/styles/[name].css",
        disable: isDevBuild
    });

    return [{
        mode: isDevBuild ? 'development' : 'production',
        devtool: 'inline-source-map',
        stats: { modules: false },
        entry: {
            'main': './ClientApp/js/main.tsx',
            'styles': './ClientApp/styles/main.scss'
        },
        watchOptions: {
            ignored: /node_modules/
        },
        output: {
            filename: "dist/js/[name].js",
            path: path.join(outputDir, 'wwwroot'),
            publicPath: '/'
        },

        resolve: {
            // Add '.ts' and '.tsx' as resolvable extensions.
            extensions: [".ts", ".tsx", ".js", ".json"]
        },

        devServer: {
            hot: true
        },

        module: {
            rules: [
                // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
                {
                    test: /\.tsx?$/,
                    include: /ClientApp/,
                    loader: [
                        {
                            loader: 'awesome-typescript-loader',
                            options: {
                                useCache: true,
                                useBabel: true,
                                babelOptions: {
                                    babelrc: false,
                                    plugins: ['react-hot-loader/babel'],
                                },
                                babelCore: '@babel/core'
                            }
                        }
                    ]
                },

                // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
                { enforce: "pre", test: /\.js$/, loader: "source-map-loader" },

                // Any files that are referenced
                {
                    test: /\.(woff|woff2|eot|ttf|otf|svg|jpg|png|jpeg)(\?|$)/, use:
                    {
                        loader: 'url-loader',
                        options: {
                            // limit files to 50k
                            limit: 50000,
                            name: 'dist/assets/[name].[hash].[ext]'
                        }
                    }
                },

                // Compile all SCSS files
                {
                    test: /\.s[ac]ss$/,
                    use: extractSass.extract({
                        fallback: 'style-loader',
                        use: [
                            {
                                loader: 'css-loader',
                                options: { importLoaders: 2 }
                            },
                            {
                                loader: 'postcss-loader',
                                options: {
                                    ident: 'postcss',
                                    sourceMap: isDevBuild,
                                    plugins: [
                                        autoprefixer
                                    ]
                                }
                            },
                            'resolve-url-loader',
                            'sass-loader',
                        ]
                    })
                }
            ]
        },

        plugins: [
            new CleanWebpackPlugin(
                path.join(outputDir, 'wwwroot', 'dist'),
                {
                    exclude: path.join(outputDir, 'wwwroot', 'dist', 'js', 'vendor.js')
                }),
            new CheckerPlugin(),
            new webpack.DllReferencePlugin({
                context: __dirname,
                manifest: require(tempDir + '/vendor-manifest.json'),
            }),
            extractSass,
        ]
    }];

};

Webpack.config.vendor.js

const path = require('path');
const webpack = require('webpack');

let tempDir = '../../obj/WebAssess';

module.exports = (env) => {
    const isDevBuild = !(env && env.prod);

    const outputDir = (env && env.publishDir)
        ? env.publishDir
        : __dirname;

    return [{
        mode: isDevBuild ? 'development' : 'production',
        stats: { modules: false },
        resolve: {
            extensions: ['.js']
        },
        module: {
            rules: [
                { test: /\.(png|woff|woff2|eot|ttf|svg)(\?|$)/, use: 'url-loader?limit=100000' }
            ]
        },
        entry: {
            vendor: ['react', 'react-dom', 'react-router', 'react-router-dom', 'bootstrap', 'jquery'],
        },
        output: {
            path: path.join(outputDir, 'wwwroot'),
            publicPath: '/',
            library: '[name]_[hash]',
            filename: 'dist/js/[name].js',
        },
        plugins: [
            new webpack.DllPlugin({
                path: path.join(tempDir, '[name]-manifest.json'),
                name: '[name]_[hash]',
            })
        ]
    }];
};

9. Run "webpack --config webpack.config.vendor.js" from the command line to create the "vendor-manifest.json" file.

10. Add "tsconfig.json" with the default template

{
  "typeAcquisition": { "enable": true },
  "compileOnSave": false,
  "compilerOptions": {
    "sourceMap": true,
    "module": "commonjs",
    "target": "es6",
    "noImplicitAny": true,
    "jsx": "react",
    "outDir": "wwwroot/dist",
    "moduleResolution": "node"
  },
  "exclude": [
    "node_modules",
    "wwwroot"
  ]

}

11. Build the project.

12. Run "npm run webpack" from command prompt.

13. Add "ClientApp\js\main.tsx" (typescript) file in the project

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './components/App';


ReactDOM.render(<App />, document.getElementById('root'))

"ClientApp\styles\main.scss"(stylesheets)

import * as React from "react";

export default class App extends React.Component{
    render(){
        return (
            <div>
                <h1>WebAssess Portal</h1>
                </div>
            );
    }

}


14. Change the main.cshtml page as follows


@{
  ViewData["Title"] = "WebAssess";
}

<div id="root"></div>

@section Scripts {
  <script src="~/dist/js/main.js" asp-append-version="true"></script>

}

and add shared/_layout.cshtml page


<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>@ViewData["Title"]</title>

  <script src="~/dist/js/vendor.js" asp-append-version="true"></script>

  <environment exclude="Development">
    <link rel="stylesheet" href="~/dist/styles/styles.css" asp-append-version="true" />
  </environment>
  <environment include="Development">
    <script src="~/dist/js/styles.js" asp-append-version="true"></script>
  </environment>
</head>
<body>
  @RenderBody()
  @RenderSection("Scripts", required: false)
</body>

</html>


15. Run the application now. This will give you the initial website with WebPack, React and MVC frameworks installed and scale it to a large application.

Comments