Introduction to the Webpack
Webpack is the module bundler for modern javascript oriented applications. It has a configuration based setup. There are four basic concepts or core parts in webpack which are Entry, Output, Loaders and plugins. We will be discussed these concepts to have a better idea about core functions webpack performing.
- Entry
- Output
- Loaders
- Plugins
Entry
Webpack basically creates a graph of all of your dependencies and for every application there is a single starting point which is called the entry point. It tells webpack where to start and bundle all related dependencies.
In webpack we define entry point using entry property in configuration file.
- module.exports = {
- entry: {
- "polyfills": "./Angular2/polyfills.ts",
- "vendor": "./Angular2/vendor.ts",
- "app": "./Angular2/main.ts"
- },
- },
In entry object we declare key as name of the file and value as the path associated with it.
Output
You can think of it like some one has interacted with a web application in a way to input some data and execute the command by pressing button so that after processing it will show you processed output in any form which you initiated just like in webpack if there is an entry point to tell the webpack but after creating a bundle there must be some destination to place these bundles in webpack and we use output property to place the bundle files.
- module.exports = {
- output: {
- path: "./Views/Home",
- filename: '../../angularBundle/[name].[hash].build.js'
- },
In output object we use path where to create directory if it's already not created and filename as filenaming syntax starting with the directory_name/file_name_from_entry_key_value.randomhashvalue.js
Loaders
The basic goal of the loaders is to load the type of all assets/files and every file is a module in webpack language which it processed and converted to javascript as webpack only if it understands javascript.
For transformation process webpack has loaders for all the file types supported like for .ts file types 'awesome-typescript-loader','source-map-loader','tslint-loader' webpack uses these loaders and so on.
To register the file types we will use module property and use the rules where we define the file name in test and loader type in loader property like this.
- module: {
- rules: [{
- test: /\.ts$/,
- loaders: ['awesome-typescript-loader', 'source-map-loader', 'tslint-loader']
- }, {
- test: /\.(png|jpg|gif|woff|woff2|ttf|svg|eot)$/,
- loader: 'file-loader?name=assets/[name]-[hash:6].[ext]'
- }, {
- test: /favicon.ico$/,
- loader: 'file-loader?name=/[name].[ext]'
- }, {
- test: /\.css$/,
- loader: 'style-loader!css-loader'
- }, {
- test: /\.scss$/,
- exclude: /node_modules/,
- loaders: ['style-loader', 'css-loader', 'sass-loader']
- }, {
- test: /\.html$/,
- loader: 'raw-loader'
- }],
Plugins
The fourth and the last functional part of the webpack is the plugins which will aid the webpack to do some processing and actions after creating bundle like if the created bundle is not a minified webpack use some uglified plugin to minify code and other related plugins as per user need.
Plugins property is used to add new plugin initialized with a new keyword.
- plugins: [
- new webpack.optimize.CommonsChunkPlugin({
- name: ['app', 'polyfills', ]
- }),
- new CleanWebpackPlugin(
- ['./AngularBundle', ]),
- new HtmlWebpackPlugin({
- template: "./Views/Home/loader",
- filename: "./Index.cshtml",
- inject: false,
- }),
- new CopyWebpackPlugin([{
- from: './angular2/images/*.*',
- to: 'assets/',
- flatten: true
- }])
- ]
Let’s move step by step to configure our app for webpack.
Step 1
Create the package.json on the root of the application.
using command prompt run command
- npm init -f
Step 2 Installing Development Dependencies
The development dependencies are those libraries, which are required only to develop the application. For Example javascript libraries for unit tests, minification, module bundlers are required only at the time of development of the application.
Our Angular 2 application needs Typescript. Webpack module, loaders & plugins etc.
Install the required webpack npm package.
- npm install webpack webpack-dev-server --save-dev
Step 3
install webpack loaders
- npm install angular2-template-loader awesome-typescript-loader css-loader file-loader
-
- html-loader null-loader raw-loader style-loader to-string-loader --save-dev
Step 4
install webpack plugins
- npm install html-webpack-plugin webpack-merge extract-text-webpack-plugin --save-dev
Step 5
install other dependencies
- npm install rimraf --save-dev
Step 6
Configuring our application
Create the file tsconfig.json in the root folder of our project and copy the following code into it.
- {
- "compilerOptions": {
- "module": "es2015",
- "target": "es5",
- "module": "commonjs",
- "moduleResolution": "node",
- "sourceMap": true,
- "emitDecoratorMetadata": true,
- "experimentalDecorators": true,
- "removeComments": false,
- "noImplicitAny": false,
- "skipLibCheck": true,
- "lib": ["es2015", "dom"],
- "types": ["node"]
- },
- "awesomeTypescriptLoaderOptions": {
- "useWebpackText": true
- },
- "compileOnSave": false,
- "buildOnSave": false
- }
Step 7 Webpack Bundle
The next step is to configure the Webpack. Webpack allows us to bundle all our javascript files into one or more files. Let us create TWO bundles in our application
In the first bundle, we add all our application code like components, service, modules etc. We call it as an app. We do not have to create a separate file to that. Our main.ts file will be the starting point for this bundle.
In the second bundle, we include the polyfills we require to run Angular applications in most modern browsers. Create a file called polyfills.ts and copy the following code.
- import 'ie-shim';
- import 'core-js/es6/symbol';
- import 'core-js/es6/object';
- import 'core-js/es6/function';
- import 'core-js/es6/parse-int';
- import 'core-js/es6/parse-float';
- import 'core-js/es6/number';
- import 'core-js/es6/math';
- import 'core-js/es6/string';
- import 'core-js/es6/date';
- import 'core-js/es6/array';
- import 'core-js/es6/regexp';
- import 'core-js/es6/map';
- import 'core-js/es6/set';
- import 'core-js/es6/weak-map';
- import 'core-js/es6/weak-set';
- import 'core-js/es6/typed';
- import 'core-js/es6/reflect';
- import 'core-js/es7/reflect';
- import 'zone.js/dist/zone';
- import 'ts-helpers';
Step 8
Webpack configuration
The next step is to configure the Webpack.
The Webpack by convention uses the webpack.config.js file to read the configuration information. Create the webpack.config.js in the root folder of our project. Add the following code.
- var environment = (process.env.NODE_ENV || "development").trim();
- if (environment === "development") {
- module.exports = require('./webpack.dev.js');
- } else {
- module.exports = require('./webpack.prod.js');
- }
The Webpack can be set up so that you can have a separate configuration option for testing , development, and production. What you need to do is to create separate config files for development, testing and production and then switch between these config file in the main configuration file.
Create webpack.dev.js under the config folder and add the following code.
- var path = require('path');
- var webpack = require('webpack');
- var HtmlWebpackPlugin = require('html-webpack-plugin');
- var CopyWebpackPlugin = require('copy-webpack-plugin');
- var CleanWebpackPlugin = require('clean-webpack-plugin');
- console.log('@@@@@@@@@ USING DEVELOPMENT @@@@@@@@@@@@@@@');
- module.exports = {
- devtool: 'source-map',
- performance: {
- hints: false
- },
- entry: {
- "polyfills": "./Angular2/polyfills.ts",
-
- "app": "./Angular2/main.ts"
- },
- output: {
- path: "./Views/Home",
- filename: '../../angularBundle/[name].[hash].build.js'
- },
- resolve: {
- extensions: ['.ts', '.js', '.json', '.css', '.scss', '.html', '.cshtml'],
- modules: [path.resolve(__dirname, './src'), 'node_modules']
- },
- devServer: {
- historyApiFallback: true,
- contentBase: path.join(__dirname, '/wwwroot/'),
- watchOptions: {
- aggregateTimeout: 300,
- poll: 1000
- }
- },
- module: {
- rules: [{
- test: /\.ts$/,
- loaders: ['awesome-typescript-loader', 'source-map-loader', 'tslint-loader']
- }, {
- test: /\.(png|jpg|gif|woff|woff2|ttf|svg|eot)$/,
- loader: 'file-loader?name=assets/[name]-[hash:6].[ext]'
- }, {
- test: /favicon.ico$/,
- loader: 'file-loader?name=/[name].[ext]'
- }, {
- test: /\.css$/,
- loader: 'style-loader!css-loader'
- }, {
- test: /\.scss$/,
- exclude: /node_modules/,
- loaders: ['style-loader', 'css-loader', 'sass-loader']
- }, {
- test: /\.html$/,
- loader: 'raw-loader'
- }],
- exprContextCritical: false
- },
- plugins: [
- new webpack.optimize.CommonsChunkPlugin({
- name: ['app', 'polyfills', ]
- }),
- new CleanWebpackPlugin(
- ['./AngularBundle', ]),
- new HtmlWebpackPlugin({
- template: "./Views/Home/loader",
- filename: "./Index.cshtml",
- inject: false,
- }),
- new CopyWebpackPlugin([{
- from: './angular2/images/*.*',
- to: 'assets/',
- flatten: true
- }])
- ]
- };
Step 9
Finally, Open the package.json and replace the scripts options with the code below.
- "ngc": "ngc -p ./tsconfig-aot.json",
- "start": "concurrently \"webpack-dev-server --hot --inline --port 8080\" \"dotnet run\" ",
- "webpack-dev": "set NODE_ENV=development && webpack",
- "webpack-production": "set NODE_ENV=production && webpack",
- "build-dev": "npm run webpack-dev",
- "build-production": "npm run ngc && npm run webpack-production",
- "watch-webpack-dev": "set NODE_ENV=development && webpack --watch --color",
- "watch-webpack-production": "npm run build-production --watch --color",
- "publish-for-iis": "npm run build-production && dotnet publish -c Release"
Step 10
create the loader.cshtml file in View/Home/loader.cshtml
Add the generated chunks to the loader.cshtml file
Create the loader.cshtml file and add the index.cshtml view code inside it and after the component selector code add this code.
- <% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
- <script src="<%= htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>
- <% } %>
Also add the jquery and the bootstrap script and css blocks as required.
- <script src="~/Content/js/jquery-3.1.1.min.js"></script>
- <script src="~/Content/js/bootstrap.min.js"></script>
- <script src="~/Content/js/datepicker.min.js"></script>
- <script src="~/Content/js/timepicker.js"></script>
Output