This paper optimizes the code of production environment from three aspects: code compression, code separation and style separation. These are the simplest configurations, but if they are implemented in a project, more configurations will need to be added depending on the project.


preface

This article is about how to compress the code in the production environment. If you are not familiar with Webpack, you can take a look at my last article: Build a Webpack development environment configuration from scratch.

This article project code location: source code address


Environment set up

The project structure

First write a project, initialize NPM, then install Webpack locally, then install WebPack-CLI (this tool is used to run WebPack on the command line) :

$ mkdir webpack-prod-demo

$ cd webpack-prod-demo

$ npm init -y

$ npm install webpack webpack-cli --save-dev
Copy the code

project

webpack-prod-demo
|- package.json
|- /public
  |- index.html
|- /src
  |- index.js
  |- index.css
Copy the code

pubic/index.html


      
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Webpack production environment configuration</title>
</head>
<body>
    
</body>
</html>
Copy the code

index.js

import './index.css';

function component() {
    var element = document.createElement('div');

    element.innerHTML = 'Hello World';
  
    return element;
}
  
document.body.appendChild(component());
Copy the code

index.css

div {
    color: blue;
    text-align: center;
}
Copy the code

package.json

{
  "name": "webpack-prod-demo"."version": "1.0.0"."description": ""."private": true."scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"."build": "webpack --config webpack.config.js"
  },
  "keywords": []."author": ""."license": "ISC"
}
Copy the code

Configure the webpack.config.js file

Create the webpack.config.js file in the root directory and perform basic configuration

Installing a plug-in

# installed Babel - loader
$ npm install babel-core babel-loader@7 --save-dev

Install the Babel presets
$ npm install babel-preset-env babel-preset-stage-0 --save-dev

Install Babel plugins
$ npm install babel-plugin-transform-class-properties babel-plugin-transform-runtime babel-runtime --save-dev

Install the rest of the required loader
$ npm install css-loader style-loader file-loader csv-loader xml-loader html-loader markdown-loader --save-dev

Install the WebPack plugin
$ npm install clean-webpack-plugin html-webpack-plugin friendly-errors-webpack-plugin --save-dev
Copy the code

Configuration webpack. Config. Js:

webpack.config.js

const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');

module.exports = {
    mode: 'development'.devtool: 'hidden-source-map'.entry: './src/index.js'.output: {
        filename: '[name]-[hash:8].js'.path: path.resolve(__dirname, 'dist')},plugins: [
        new HTMLWebpackPlugin({
            // The title of the HTML document to be generated
            title: 'Webpack Production Environment Configuration '.// Webpack generates the template path
            template: './public/index.html'
        }),
        New CleanWebpackPlugin(Paths [, {options}])
        new CleanWebpackPlugin(['dist']),
        // Make a friendly prompt at the command line
        new FriendlyErrorsWebpackPlugin()
    ],
    module: {
        rules: [{test: /\.js/.include: path.resolve(__dirname, 'src'),
                loader: 'babel-loader? cacheDirectory'
            },
            / / CSS
            {
                test: /\.css$/.include: path.resolve(__dirname, 'src'),
                use: [
                    'style-loader'.// You can also add some configuration to the loader
                    {
                        loader: 'css-loader'.options: {
                            / / open sourceMop
                            sourceMap: true}}},// Parse image resources
            {
                test: /\.(png|svg|jpg|gif)$/.use: [
                    'file-loader']},// Parse the font
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/.use: [
                    'file-loader']},// Parse data resources
            {
                test: /\.(csv|tsv)$/.use: [
                    'csv-loader']},// Parse data resources
            {
                test: /\.xml$/.use: [
                    'xml-loader']},// Parse the MakeDown file
            {
                test: /\.md$/.use: [
                    "html-loader"."markdown-loader"}]}}Copy the code

Create the.babelrc file in the project root directory

.babelrc

{
    "presets": ["env"."stage-0"]."plugins": [
        "transform-runtime"."transform-class-properties"]}Copy the code

Run the project after the basic configuration is complete

Run the command from the command line:

$ npm run build
Copy the code

At this time, open the HTML file under the dist folder in the browser, and the Blue Hello World is displayed on the page

Dist file size:

Set the mode toproduction

webpack.config.js

. module.exports = {mode: 'production'. }Copy the code

Run the project after setting it up for production

Run the command from the command line:

$ npm run build
Copy the code

At this point, open the HTML file under the dist folder in the browser, and the Blue Hello World can still be displayed on the page

Dist file size:

The focus of this article: optimizing packaging

Install the required plug-ins:

Install plugins that compress JS and CSS code
$ npm install uglifyjs-webpack-plugin optimize-css-assets-webpack-plugin --save-dev

Install plugins that extract CSS
$ npm install mini-css-extract-plugin --save-dev
Copy the code

Uglifyjs-webpack-plugin and optimize- CSS-assets-webpack-plugin

webpack.config.js

. ;const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");

module.exports = { ... .optimization: {
        // Package compressed js/ CSS files
        minimizer: [
            new UglifyJsPlugin({
                uglifyOptions: {
                    compress: {
                        // UglifyJs deletes unused code without warning
                        warnings: false.// Delete all 'console' statements, compatible with Internet Explorer
                        drop_console: true.// Inline variables that are defined but used only once
                        collapse_vars: true.// Extract static values that occur multiple times but are not defined as variables to reference
                        reduce_vars: true,},output: {
                        // Most compact output
                        beautify: false.// Delete all comments
                        comments: false,}}}),new OptimizeCSSAssetsPlugin({
                cssProcessorOptions: {
                    safe: true}}]}}Copy the code

Uglifyjs-webpack-plugin Please refer to the plugin documentation for more configurations.

Optimize – CSS -assets-webpack-plugin See the plugin documentation for more details.

The mini – CSS – extract – the use of the plugin

Note: MiniCssExtractPlugin. Loader used with style – loader problem may come up. So I’m going to remove the style-loader.

webpack.config.js

. ;const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    ...
    plugins: [
        ...,
        // Extract the CSS file
        new MiniCssExtractPlugin({
            filename: '[name].[contenthash:8].css'.chunkFilename: '[name].[contenthash:8].chunk.css'})].module: [
        rules: [
            ...,
            / / CSS
            {
                test: /\.css$/.include: path.resolve(__dirname, 'src'),
                use: [{loader: MiniCssExtractPlugin.loader
                    },
                    // You can also add some configuration to the loader
                    {
                        loader: 'css-loader'.options: {
                            / / open sourceMop
                            sourceMap: true}}]},... ] ]}Copy the code

For more configuration, please refer to the mini-CSS-extract-Plugin documentation.

The chunk split

webpack.config.js

. ;module.exports = { ... .optimization: {
        // Package compressed js/ CSS filesminimizer: [ ... ] .splitChunks: {
            chunks: 'all'}}}Copy the code

For details about splitChunks configuration, see the official documentation.

To distinguish the environment

When developing web pages, there are usually multiple operating environments, such as:

  • An environment that facilitates development and debugging during development
  • Publish online to the user’s operating environment

In order to reuse the code as much as possible, we need to have a mechanism to differentiate the environment in the source code depending on the environment in which the target code is to run. Environments can be differentiated using the DefinePlugin plugin built into Webpack.

The reason for environment differentiation: Many third-party libraries have also been optimized for environment differentiation

  • Development environment: contains type checking, HTML element checking, and other warning log code for developers
  • Online environment: Removed all developer-specific code, leaving only the parts that make React work to optimize size and performance

Note: NODE_ENV and ‘production’ values are community conventions and are often used to distinguish between development and online environments.

Configuration:

webpack.config.js

. module.exports = { ... .plugins: [...// Distinguish the environment
        new webpack.DefinePlugin({
            // Define the NODE_ENV environment variable as production
            'process.env': {
                NODE_ENV: JSON.stringify('production'}})],... }Copy the code

Run the project after configuration optimization

Run the command from the command line:

$ npm run build
Copy the code

At this point, open the HTML file under the dist folder in the browser, and the Blue Hello World can still be displayed normally on the page

Dist file size:

The final code of the webpack.config.js file

The rest of the files are basically unmodified. Post the webpack.config.js code here

webpack.config.js

const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');


module.exports = {
    mode: 'production'.devtool: 'hidden-source-map'.entry: './src/index.js'.output: {
        filename: '[name]-[hash:8].js'.path: path.resolve(__dirname, 'dist')},plugins: [
        new HTMLWebpackPlugin({
            // The title of the HTML document to be generated
            title: 'Webpack Development Environment Configuration '.// Webpack generates the template path
            template: './public/index.html'
        }),
        New CleanWebpackPlugin(Paths [, {options}])
        new CleanWebpackPlugin(['dist']),
        // Make a friendly prompt at the command line
        new FriendlyErrorsWebpackPlugin(),
        // Extract the CSS file
        new MiniCssExtractPlugin({
            filename: '[name].[contenthash:8].css'.chunkFilename: '[name].[contenthash:8].chunk.css'
        }),
        // Distinguish the environment
        new webpack.DefinePlugin({
            // Define the NODE_ENV environment variable as production
            'process.env': {
                NODE_ENV: JSON.stringify('production')}})],module: {
        rules: [{test: /\.js/.include: path.resolve(__dirname, 'src'),
                loader: 'babel-loader? cacheDirectory'
            },
            / / CSS
            {
                test: /\.css$/.include: path.resolve(__dirname, 'src'),
                use: [{loader: MiniCssExtractPlugin.loader
                    },
                    // You can also add some configuration to the loader
                    {
                        loader: 'css-loader'.options: {
                            / / open sourceMop
                            sourceMap: true}}},// Parse image resources
            {
                test: /\.(png|svg|jpg|gif)$/.use: [
                    'file-loader']},// Parse the font
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/.use: [
                    'file-loader']},// Parse data resources
            {
                test: /\.(csv|tsv)$/.use: [
                    'csv-loader']},// Parse data resources
            {
                test: /\.xml$/.use: [
                    'xml-loader']},// Parse the MakeDown file
            {
                test: /\.md$/.use: [
                    "html-loader"."markdown-loader"]]}},optimization: {
        // Package compressed js/ CSS files
        minimizer: [
            new UglifyJsPlugin({
                uglifyOptions: {
                    compress: {
                        // UglifyJs deletes unused code without warning
                        warnings: false.// Delete all 'console' statements, compatible with Internet Explorer
                        drop_console: true.// Inline variables that are defined but used only once
                        collapse_vars: true.// Extract static values that occur multiple times but are not defined as variables to reference
                        reduce_vars: true,},output: {
                        // Most compact output
                        beautify: false.// Delete all comments
                        comments: false,}}}),new OptimizeCSSAssetsPlugin({
                cssProcessorOptions: {
                    safe: true}})].splitChunks: {
            chunks: 'all'}}}Copy the code

contrast

Through the comparison of three packages, it can be seen that:

  • After the first common configuration is packed, the package size is 48.1K
  • The package size is 39.0K after it is set to the production environment for the second time
  • The package is optimized for the third time and the package size is 1.46K

At present, this project is a JS file, the amount of code is very small, but you can still see the effect of optimization. If the project is larger, the optimization effect will be more obvious. Of course, more configuration may be required.


Program source code

The source address


conclusion

This article is just a simple optimization for code packaging in production, but more configuration may be required as the project goes live. In fact, no matter how many tutorials, in fact, the configuration can not necessarily meet their own requirements. In the development process, you still need to configure according to your requirements.

In fact, learning Webpack is not difficult, according to the official website instructions and guidelines, in fact, basic can use. The difficulty is the configuration of various Loaders and plugins themselves. All of these need to be researched in depth on the Loader and Plugin websites. So if you want to do a better webPack configuration, you still need to pay more attention to the emergence of the latest technology, and collect useful plug-ins and configurations. Every little makes a little bit of a difference, and over time a better project scaffolding can be built (which is currently my goal).