Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
September 9, 2021 09:34 am GMT

Webpack Academy 6: Split your config for dev & prod mode

So from now we manage a lot of things, but we need to divide our config into two parts:

  • Dev part (for developer)

  • Prod part (when we deploy our application on the web)

Until now we just focus on the Prod part!

So in this article, we will split our config into 3 files!

  • Common config webpack

  • Prod config

  • Dev config

Common config webpack

Some properties are common to dev & prod config files, so we can create a file that will contain these fields to avoid repeating code!

Before starting we need to install a package named webpack-merge, which will merge two configs files into one! So we can merge-common file with another file !

After this, we create a common config file

const { CleanWebpackPlugin } = require("clean-webpack-plugin")const HtmlWebpackPlugin = require('html-webpack-plugin')const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPluginconst cdn = require("./cdn")const config = {    // Webpack start from this entry point    entry: {        myApp: [            "./src/style.css",            "./src/main.js",        ],    },    // External lib that will not be put in bundle but use from CDN    externals: {        lodash: '_',    },    plugins: [        new CleanWebpackPlugin(),        new HtmlWebpackPlugin({            title: 'Webpack academy title',            template: './src/index.html',            inject: 'body',            cdn,            minify: {                removeComments: true,                collapseWhitespace: false            }        }),        new BundleAnalyzerPlugin({            openAnalyzer: true,            analyzerMode: 'server',        })    ],}module.exports = config

In common config we need to use bundle analyser for prod & dev mode, we need also HTML plugin & clean webpack !

We also need to use cdn !

And we create a prod config file !

Prod config file

const commonConfig = require("./webpack.config.common")const merge = require('webpack-merge')const MiniCssExtractPlugin = require("mini-css-extract-plugin")const config = {    mode: "production",    module: {        rules: [            {                // Match file extension                test: /\.css$/,                // Order of loader from bottom to up                use: [                    MiniCssExtractPlugin.loader,                    'css-loader'                ],            }        ]    },    // This is the output of Webpack    output: {        // From current folder + dist folder that will contains all bundle        path: path.resolve(__dirname, "dist/"),        filename: "[contenthash:8].js"    },    optimization: {        minimize: true,    },    plugins: [        new MiniCssExtractPlugin({            // Name output by extract            filename: "style.css",        }),    ],}// Merge commonConfig with prod config, priority to prod configmodule.exports = merge(commonConfig, {    ...config,})

In prod mode we need to use hash, extract css & minimize bundle code !

It's almost finished for the prod part, we need to rename cdn file to cdn.prod.js since we will use two separate files for cdn in prod & dev mode !

And we need to edit script file

"build": "cross-env --env.NODE_ENV=prod webpack --config webpack.config.prod.js"

And it's finished from now for the prod part !

All things are working since before ! It's a good start to continue and go on the prod part!

Dev config file

Let's start by creating cdn.dev !

Unlike prod cdn, we will NOT use the minify version of library ! We will just use the classic !

module.exports = {    js: [        "https://unpkg.com/[email protected]/lodash.js",    ],}

After this we need to install webpack-dev-server, which serves to handle dev service like a dev server for developer !

And create the dev config

const path = require("path")const commonConfig = require("./webpack.config.common")const merge = require('webpack-merge')const config = {    mode: "development",    devServer: {        // Show info about dev server        noInfo: false,        // Port of dev server        port: 8080,        // Asking the server to fallback to index.html in the event that a requested resource cannot be found, need to vue router        historyApiFallback: true,        // Allows https in dev server        // Use this https://stackoverflow.com/questions/35531347/localhost-blocked-on-chrome-with-privacy-error for allow https in localhost directly on chrome        https: true,    },    // This is the output of Webpack    output: {        // From current folder + dist folder that will contains all bundle        path: path.resolve(__dirname, "dist/"),        filename: "bundle.dev.js"    },    module: {        rules: [            {                // Match file extension                test: /\.css$/,                // Use multiple loader                // Order => from bottom to top                use: [                    'style-loader',                    'css-loader'                ],            }        ]    }}// Merge commonConfig with prod config, priority to prod configmodule.exports = merge(commonConfig, {    ...config,})

For css part we need to use style-loader since we need to inject style in the DOM !

We use some properties like port, https etc... (check comment above)

But on thing is very interesting and I should explain you

historyApiFallback:

When you use a framework like Vuejs or React, you will choose between two things -> Use Router in front part or back part.

If you use vuejs for example and you need to use VueRouter (handling routing of your app in the Front part).

You will need to inform the current server that hosts your app (in my case webpack server) that you handle route by the front and not by the server (back).

But why ?

For example if you use router front and you will try this URL

https://toto.com/test

The server will try to access to /test file from the server files, and it will get nothing since it's not an existing file (because you handle routing by front). And you will get a 404 !

To avoid this behavior in our case, we need to tell the server -> If you have a 404, access to the root file (main file) and not looking for /test file

And after this you can enter any URL and your project will works !

So this options historyApiFallback is just an option to prevent this if you use Router in the front part, you should put true ! Else put false !

We almost finish

Create the command to run our app in dev mode

"dev": "cross-env --env.NODE_ENV=dev webpack serve --hot --config webpack.config.dev.js",

webpack serve --hot: Command to run webpack server in hot reload mode (when a file is changed, we reload our project automatically)

Source map

We will not get in details about this, if you want to check this URL -> https://blog.teamtreehouse.com/introduction-source-maps

To be short, in dev mode we will need to debug some files, if we don't use source map, we will have some files that are a little weird, for example, our main.js

lodash__WEBPACK_IMPORTED_MODULE_1___default().cloneDeep({})console.log(_three__WEBPACK_IMPORTED_MODULE_0__.three)document.getElementById("button").addEventListener("click", function() {    jsonObjectImport().then(jsonObject => console.log(jsonObject.default))})

Here it's not a problem, but with big files we can have some trouble to debug this !

So source map is our hero !

devtool: 'eval-cheap-source-map',

(You have a lot of choices about source map, for me the best to use in dev is 'eval-cheap-source-map'), check at this URL to have more information: https://webpack.js.org/configuration/devtool/

When you want to debug the main.js, you will see another file like main.js?56d7 and this is this file that we will need to debug ! Open it and

import { three } from './three'import _ from 'lodash'const jsonObjectImport = async () => import(/* webpackChunkName: "myChunkName" */ "./big-object.json")_.cloneDeep({})console.log(three)document.getElementById("button").addEventListener("click", function() {    jsonObjectImport().then(jsonObject => console.log(jsonObject.default))})

It's like our original main.js file !

To summarise source map :

When we bundle our code with Webpack, it will compile our original file into another special file (can be weird), so if we want to debug our code, we will have this special file that is different from the original file code.

To fix this we can use source map that will keep track of our original file (each original file has a special hash). So if we need to debug code we can find the file like the original file !

Well done !

We made it ! We manage to split the original config into two parts !

We almost finish the webpack academy!

I hope you like this, You can check the source code at this commit

Note: We create two more commands for bundle analyzer, in prod and dev mode if we need to check bundle size in both cases

I hope you like this reading!

If you want to have a nice article to read about web dev, you can subscribe to my FREE newsletter & get a cheatlist about Javascript at this URL

MY NEWSLETTER

You can SUPPORT MY WORKS

You can follow me on

Twitter : https://twitter.com/code__oz

Github: https://github.com/Code-Oz

And you can mark this article!


Original Link: https://dev.to/codeoz/webpack-academy-6-split-your-config-for-dev-prod-mode-2le7

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To