Two projects one webpack package

Keywords: Front-end Webpack npm Vue Javascript

File dependency is complex, static resource request efficiency is low, modularization support is not friendly, browser compatibility with advanced JS is low? That's the time to learn about webback

I. a brief understanding of webpack

(1) concept

Webpack is a static module packaging builder for JavaScript applications. When processing an application, webpack recursively builds a dependency graph that contains each module the application needs, and then packages all these modules into one or more bundle s. Webpack provides friendly modular support, code compression confusion, advanced js compatibility, and performance optimization.

(2) core

1. Entry: Specifies the file from which the webpack package compilation starts

The entry point indicates which module the web pack uses as the start of building its internal dependency graph. After entering the entry point, webpack will find out which modules and libraries are dependent on the entry point (directly and indirectly).

webpack.config.js:

module.exports = {
 entry: {
    main: './src' //Package entry to specify one entry start point (or multiple entry start points, default value is. / src)
  },
 entry: './src', //This is the abbreviation above. It's equivalent
 entry: {
  home: "./home.js",
  about: "./about.js",
  contact: "./contact.js"
 },//Object method specifies multiple entries. If you want multiple dependencies to be injected into a module together, pass "file path array" to the entry attribute.
 entry: () => new Promise((resolve) => resolve(['./demo', './demo2'])),//Dynamic entry, when combined with the output.library option: if an array is passed in, only the last entry is exported
};

2. Output: specify the path and file name of the compiled web pack

The output property tells webpack where to output the bundles it creates and how to name the files. Basically, the entire application structure will be compiled into the folder of the output path you specify.

webpack.config.js:

const path = require('path');

module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist'),//Package folder name, default value is. / dist
    filename: '[name].js'//Entry file name
  }
};

3. Loader: language unrecognized by webpack is translated by loader

The loader is used to convert some types of modules. The weback only understands JavaScript. The loader can convert all types of files into the effective ones that weback can handle modular . loader can import any type of module (such as. css), which is a unique function of webpack. Other packaging tools may not support it.

webpack.config.js:

const path = require('path');

const config = {
  module: {
    rules: [//When defining a loader in a webpack configuration, you need to define it in module.rules, which contains two "required properties": test and use
      { 
        test: /\.txt$/, //test defines a class of files that need to be converted with the corresponding loader
        use: 'raw-loader' //Use defines which loader to use for conversion
      } 
    ]
  }
};

module.exports = config;

4. Plugins: functions that cannot be completed by webback are completed by plug-ins

Plug in interface It is extremely powerful and can be used to handle various tasks. Use the plug-in through require(), and then add it to the plugins array. Most plug-ins can be customized through options.

webpack.config.js:

const HtmlWebpackPlugin = require('html-webpack-plugin'); // Installation through npm
const webpack = require('webpack'); // For accessing built-in plug-ins

const config = {
  plugins: [
    //To use the same plug-in multiple times for different purposes in a configuration file, you need to create an instance of it by using the new operator
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

module.exports = config;

5. Mode: determine the development environment or production environment through the mode to load different configurations

module.exports = {
  mode: 'production'//Enable the built-in optimization of webback in the corresponding mode by selecting development or production
};

6. Configuration

Webback needs to pass in a configuration object, which is parsed according to the properties defined by the object, so few webback configurations look exactly the same. The configuration file of webpack is a JavaScript file that exports an object. You can use webpack in two ways (terminal, Node.js).

webpack configuration is a standard Node.js CommonJS module. You can:

  • Import other files through require(...)
  • Use npm's utility functions with....)
  • Use JavaScript to control flow expressions, such as the?: operator
  • Use constants or variables for common values
  • Write and execute functions to generate partial configuration

The following practices should be avoided:

  • When using the webpack command line interface (CLI), you should write your own command line interface (CLI), or Use -- env )To access the command line interface (CLI) parameters
  • Export indefinite values (two calls to webpack should produce the same output file)
  • Write a long configuration, which should be split into multiple files

II. Build one

(1) prerequisite

Webpack configuration is the standard Node.js CommonJS module. Before installing webpack, make sure that you have installed the Node.js The latest version of, using the old version may encounter various problems (may be lack of webback function or related package package).

(2) preparations

1. Install webpack

For most projects, local installation is recommended. This makes it easier to upgrade the project separately when introducing the dependency of breaking change. Global installation of webpack is not recommended. This will lock the websacks in your project to the specified version, and in projects that use different versions of websacks, it may cause the build to fail.

①Local installation
npm install --save-dev webpack //Install the latest version
npm install --save-dev webpack@<version> //Install a specific version

②Global installation 
npm install --global webpack

2. Install CLI

If you use the webpack 4 + version, you also need to install the CLI, which is used to run webpack on the command line.

npm install --save-dev webpack-cli //Webpack cli is used to run webpack on the command line

(3) hands on operation

In existing projects:

npm init -y  //Initializing webpack will automatically generate a package.json

One project package, two projects demo1 and demo2 (applicable to two projects with similar functional requirements, common places and different places):

{
  "name": "webpackstudy",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "demo1-start": "webpack-dev-server --progress --color",
    "demo2-start": "webpack-dev-server --progress --color",
    "demo1-mock": "webpack-dev-server --progress --color",
    "demo2-mock": "webpack-dev-server --progress --color",
    "demo1-te": "webpack --progress --color",
    "demo2-te": "webpack --progress --color"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "axios": "^0.19.0",
    "vue": "^2.6.10",
    "vue-pull-to": "^0.1.8",
    "vue-router": "^3.1.2",
    "vuex": "^3.1.1"
  },
  "devDependencies": {
    "@babel/core": "^7.5.5",
    "@babel/preset-env": "^7.5.5",
    "autoprefixer": "^9.6.1",
    "babel-loader": "^8.0.6",
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^3.2.0",
    "file-loader": "^4.2.0",
    "html-webpack-plugin": "^3.2.0",
    "html-withimg-loader": "^0.1.16",
    "jsonc": "^2.0.0",
    "less": "^3.10.2",
    "less-loader": "^5.0.0",
    "mini-css-extract-plugin": "^0.8.0",
    "mocker-api": "^1.8.1",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "postcss-loader": "^3.0.0",
    "style-loader": "^1.0.0",
    "terser-webpack-plugin": "^1.4.1",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "url-loader": "^2.1.0",
    "vue-loader": "^15.7.1",
    "vue-style-loader": "^4.1.2",
    "vue-template-compiler": "^2.6.10",
    "webpack": "^4.39.2",
    "webpack-cli": "^3.3.7",
    "webpack-dev-server": "^3.8.0"
  }
}
const path = require('path');
const webpack = require('webpack');
// script and link dynamically add the hash after each compile to prevent the problem of referencing cached external files; automatically create html entry files
const HtmlWebpackPlugin = require('html-webpack-plugin');
// Replace uglifyjs webback plugin with terser webback plugin to solve the problem that uglifyjs does not support es6 syntax
const TerserJSPlugin = require('terser-webpack-plugin');
// This module requires at least Node v6.9.0 and webpack v4.0.0 obfuscation codes
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
// This plug-in extracts CSS into a separate file, supports loading CSS on demand and building SourceMaps on webpack v4
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// Used to optimize and compress CSS resources
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
// When packing, the files in the previously packed directory should be cleaned up and regenerated into new ones
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
//mock data
const apiMocker = require('mocker-api');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
//Get the command after npm run
const lifecycle = process.env.npm_lifecycle_event;
//File name of npm run
const project = lifecycle.split('-')[0];
//Environment name of npm run
const proMode = lifecycle.split('-')[1] === 'te';
const envMode = lifecycle.split('-')[1];
const webpackConfig = {
    mode: proMode ? 'production' : 'development',
    //The packaging entry is main.js of each project
    entry: path.resolve(__dirname, `${project}/main.js`),
    output: {
        //The packed file directory is the respective project name + Dist
        path: path.resolve(__dirname, `${project}Dist`),
        //Source code mapping after packaging
        // devtool: proMode ?'cheap-module-eval-source-map':'hidden-source-map',
        // devtool: "inline-source-map",
        //Export js directory after packaging
        filename: 'js/[name].[hash].js',
        //js directory in block packaging
        chunkFilename: proMode ? 'js/[name].[contenthash].bundle.js' : 'js/[name].bundle.js',
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                exclude: /node_modules/,
                use: {
                    loader: 'vue-loader'
                }
            },
            {
                test: /\.(le|c)ss$/i,
                use: [
                    proMode ? MiniCssExtractPlugin.loader :
                        'vue-style-loader',
                    'css-loader',
                    'postcss-loader',
                    'less-loader',
                ],
            },
            {
                test: /\.html$/i,
                use: [
                    'html-withimg-loader'
                ]
            },
            {
                test: /\.(png|jpg|gif)$/i,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 4096,
                            name: 'img/[name].[contenthash].[ext]'
                        },
                    },
                ],
            },
            {
                test: /\.m?js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
        ]
    },
    //Start local service when configuring npm run with webpack dev server
    devServer: {
        contentBase: `./${project}Dist`,
        inline: true //Real time refresh
    },
    //optimization
    optimization: {
        // Blocking
        splitChunks: {
            chunks: 'all',
            cacheGroups: {
                vendor: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendors',
                    chunks: 'all'
                },
            }
        }
    },
    plugins: [
        new CleanWebpackPlugin(),
        //Define plug-ins - can be read in the project
        new webpack.DefinePlugin({
            'baseUrl':proMode ? 'https:www.baidu.com':JSON.stringify('localhost')
        }),
        new HtmlWebpackPlugin({
            title:'webpack Practice',
            filename: 'index.html',
            template: `${project}/index.html`,
            // Compress html file
            minify: {
                //Is it case sensitive? false by default
                caseSensitive: false,

                //Whether to abbreviate the properties in boolean format, for example: disabled="disabled" abbreviated to disabled default false
                collapseBooleanAttributes: true,
                //Remove space or not, false by default
                collapseWhitespace: true,

                //Whether to compress css in html (compression using clean css) default value is false;
                minifyCSS: true,

                //Whether to compress js in html (compression using uglify js)
                minifyJS: true,
                //Remove comment default false
                removeComments: true,
                //Prevents the escaping of the values of attributes
                preventAttributesEscaping: true,

                //Remove quotation mark of property default false
                removeAttributeQuotes: true,

                //Comments removed from scripts and styles default to false
                removeCommentsFromCDATA: true,

                //Delete empty property or not, false by default
                removeEmptyAttributes: false,

                //  If this item is enabled, there is no body and head in the generated HTML, and the html is not closed
                removeOptionalTags: false,

                //Remove extra attributes
                removeRedundantAttributes: true,

                //Delete the type attribute of script. Under h5, the type default value of script is: text/javascript default value is false
                removeScriptTypeAttributes: true,

                //Delete type attribute of style, as above
                removeStyleLinkTypeAttributes: true,

                //Use short document type, default false
                useShortDoctype: false,
            }
        }),
        new VueLoaderPlugin()
    ],
    //Directory mapping
    resolve: {
        alias: {
            '@assets': path.resolve(__dirname, `${project}/assets`),
            '@mixins': path.resolve(__dirname, `${project}/mixins`),
            '@tools': path.resolve(__dirname, `${project}/tools`),
            '@components': path.resolve(__dirname, `${project}/components`),
        }
    }
};
if (proMode) {
    webpackConfig.optimization.minimizer = [
        //Confusion grammar
        new UglifyJsPlugin({
            chunkFilter: (chunk) => {
                if (chunk.name === 'vendor') {
                    return false;
                }
                return true;
            },
            //Remove console log
            uglifyOptions: {
                compress: {
                    drop_console: true
                }
            }
        }),
        new OptimizeCssAssetsPlugin({})
    ];
    // webpackConfig.optimization.minimizer = [new TerserJSPlugin({}),
    //     new OptimizeCssAssetsPlugin({}),];
    webpackConfig.plugins.push(
        new MiniCssExtractPlugin({
            filename: proMode ? '[name].css' : '[name].[hash].css',
            chunkFilename: proMode ? '[id].css' : '[id].[hash].css',
        })
    )
} else {
    // Hot update module
    webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
    webpackConfig.devtool = 'inline-source-map';
    if (envMode == 'mock') {
        //Mock environment, enabling mock proxy service
        webpackConfig.devServer.before = (app) => {
            apiMocker(app, path.resolve(`${project}/mock/api.js`));
        };
        //Test environment for non mock matches
        webpackConfig.devServer.proxy = process.baseUrl;
    }
}
module.exports = webpackConfig;

Posted by kubis on Tue, 17 Dec 2019 20:36:34 -0800