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;