Existing introduction methods:

  • 1. Module introduction of ES Moudle
  • import header from './header.js'
  • 2. Introduction of Common JS modules
  • const header = require('./header.js')
  • 3. Introduction of CMD modules
  • @import url("fineprint.css") print
  • 4. Introduction of AMD modules
  • define([name: String], [dependencies: String[]], factoryMethod: function(...) );
  • 5. Introduction of styles
  • url(...) Or < img SRC = ".." >

What is the webpack

  • 1. Webpack is a module bundler.
  • 2, NPX can be used in the current folder.
  • 3. Webpack-cli enables the use of webpack commands on the command line. (CLI :command line interface)
  • 4. Chunks refer to the iD of each file and chunk names refer to the name of each file.

What is the loader

  • Webpack only compiles JS files by default
  • Loaders are executed from bottom to top and from right to left
  • 1, url – loader and file – loader are compiled JPG | PNG | GIF image file, such as url – loader than style – loader multiple function, can set a limit on the options, less than the limit, and then into base64, greater than the export directly
  • 2, CSS-loader and style-loader can compile CSS files, CSS-loader will find all CSS files, compile CSS files,style-loader into style tag mounted in the head tag style tag
  • 3. Sass-loader compiles SCSS files

What is the plugins

  • Plugin can help you pack things up when the Webpack is running at a certain point.
  • HtmlWebpackPlugin will automatically generate an HTML file after packaging, and automatically introduce the JS generated by packaging into this HTML file.
  • The cleanWebpackPlugin is executed before packaging. HtmlWebpackPlugin is run after it is packaged.

What is sourceMap

  • SourceMap is a mapping that knows which line in the packaged dist directory corresponds to which line in the source code. Thus more convenient debugging.
  • Inline-source-map When used, the generated.map file will become a base64 file set into JS.
  • Cheap -inline-source-map knows which row is wrong rather than which column, reducing performance costs.
  • Cheap-module-inline-source-map adds module to handle errors not only in business code but also in third-party modules.
  • Eval is not used to map relationships through Base64, but eval is used to map relationships, which is the fastest and best performance. However, in the case of more complex code, the prompt may not be comprehensive.
  • Best practice configuration: When mode is’ development ‘,cheap-module-eval-source-map, the most complete configuration, the fastest packaging speed; When mode is’ production ‘, usecheap-module-source-mapBetter configuration.
  • How sourceMap works:
  • Segmentfault.com/a/119000000…

www.html5rocks.com/en/tutorial… www.ruanyifeng.com/blog/2013/0… www.youtube.com/watch?v=NkV…

  • SourceMap uses VLQ encoding.

WebpackDevServer improves development efficiency

  • Changing the code online will automatically take effect in several ways
    • 1. Webpack — Watch will not start a server and will not restart the browser, which is quite troublesome, so it is not recommended to use it.
    • 2. Starting an HTTP server with webpack-dev-server also helps us package the code, not to the dist directory, but in memory.
    • 3. Use webpackDevMiddleware in combination with Express ().
  • Use WebPack directly in Node
const express = require('express') const webpack = require('webpack') const webpackDevMiddleware = Require ('webpack-dev-middleware') const config = require('./webpack.config.js') // Use webpack const compiler = directly in Node webpack(config) const app = express() app.use(webpackDevMiddleware(compiler, {})) app.listen(3000, () => { console.log('server is running.') })Copy the code

Hot Module Replacement: HMR: Hot Module Replacement

  • You can debug your CSS while you’re writing it

babel-loader

  • You can convert ES6 code to ES5 code
  • If you are writing business code, you need to introduce @babel/ Polyfill and configure it@babel/preset-env
  • If you are writing third-party library code, you need to introduce @babel/ plugin-transform-Runtime and configure plugins
  • Sample code:
[['@babel/preset-env', {targets: {chrome: '67'}, useBuiltIns: @babel-polyfill plugins: [['@babel/plugin-transform-runtime', {'corejs': 2, 'helpers': true, 'regenerator': true, 'useESModules': false }]] }Copy the code

Configure the react code packaging

  • use@babel/preset-react

Such as:

{
    presets: [['@babel/preset-react']]
}
Copy the code

devServer

DevServer: {// you can start a server to run contentBase: path.resolve(__dirname, 'dist'), // in which directory to feed content to the server. Compress: true, // Compress with gzip port: 9000, // port number hot: true, // Enable webPack hotOnly: True // Delete the hotOnly configuration. You do not need to manually refresh the hotOnly configuration page on the browser. }Copy the code

Tree Shaking

  • Tree-shaking is when you bring in a module, not all of the module’s code, but only one piece of code.
  • Tree Shaking only supports ES Modules. It does not support the introduction of Common JS, require

Development and production

  • SourceMap is fully configured in development to help us quickly locate code errors in the development environment. It is simpler in the Production environment, or you can generate a map file to store it.
  • In the Development environment, the generated code does not need to be compressed, as you can see in the description. In production, the code is usually compressed

optimization

Optimization: {uesdExports: true // Can make our code not import when it is not necessary to import, such as import '@css/style.css'}Copy the code

package.json

{// There are no other modules to import on demand, otherwise ['style. CSS ','@babel/polly-fill'] is configured to identify the module "sideEffects": false,}Copy the code

Code splitting. Can be divided into several files to load, improve performance

  • Code split, nothing to do with Webpack
  • Code splitting in WebPack can be done in two ways
    • 1, synchronization mode: you can use the following code to configure, automatically help you code segmentation
    Optimization: {splitChunks: {chunks: 'all' // The default is async and only code splitting is performed for asynchronous code. }}Copy the code
    • 2, asynchronous mode: import(‘ XXX ‘).then(XXX), no configuration, automatic help you split.
    • SplitChunksPlugin parameter description
    optimization: { splitChunks: { chunks: 'async', // 'async' splits asynchronous code only, 'all' splits both synchronous and asynchronous code, and 'initial' splits synchronous code minSize: If the imported code base is larger than 30KB, the code will be split. If the imported code base is smaller than 30KB, the code will not be split. MaxSize: 0, // Configure 50000, and can be divided into more vendors if greater than 50000B, but generally not. MinChunks: 1, // How many times does a module need to be 'referenced' before it can be partitioned by code? MaxAsyncRequests: 5, // All partitioned modules can partitioned up to 5 JS files maxInitialRequests: Name: true, // The name in a cacheGroup is valid cacheGroups: {// If the synchronization code is packaged, the split codes are placed in the vendors: {test: /[\\/]node_modules[\\/]/, and so forth, so that the codes are introduced in node_modules, and so are packaged in another file. And in the Verdors group, so the generated file is called, vendors-main.js, and main is your entry name. Priority: -10, // A larger value indicates a higher priority. Filename: 'vendors.js' // Set the saved name to vendors not vendor-main. js}, default: {// Default to default minChunks: 2, priority: -20, reuseExistingChunk: true, // If a module is packaged, the module is ignored when packaged. Use the previously packaged module filename: 'common.js' // change the name to common.js and place it in common.js by default}}}}Copy the code

Loadsh is a high performance use once function function. You can handle functions like strings.

Lazy Loading

async function getComponent() { return import(/* webpackChunkName:"loadsh" */ 'loadsh').then(res => { var element = document.createElement('div') element.innerHTML = _.join(['a', 'b', 'c']) return element}) const {default: _ } = await import(/* webpackChunkName:"loadsh" */ 'loadsh') const element = document.createElement('div') element.innerHTML = _.join(['a', 'b', 'c']) return element } document.addEventListener('click', () => { getComponent().then(element => { document.body.appendChild(element) }) })Copy the code
  • The above method is lazy loading. The file loadsh is not loaded at the beginning of the page. It will be loaded only after clicking.
  • Lazy loading is not a concept of Webpack, it is a concept of ES.

What is chunk?

  • Each JS file generated by packaging is a chunk

Packaging analysis

  • Github.com/webpack/ana… Git repository for webpack analysis tools
  • Webpack.docschina.org/guides/code…

Helps us analyze the code generated by packaging

Preloading, prefetching – code coverge

  • This helps us cache content for future loading while the browser is idle.
  • Use as follows:
document.addEventListener('click', () => { import(/* webpackPrefetch: true*/ './click.js').then(({default: Func}) => {func()})}) Coverge analysis: Open chrome Console, type Command + Shift + P, type Coverage.Copy the code

Code splitting of CSS files

  • Using the MiniCssExtraPLugin, it can only run in an online environment. Does not support HMR
  • Optimize – CSS -assets-webpack-plugin CSS code merge and compress
  • Configure in Optimization
splitChunks: { cacheGroups: { styles: { name: 'styles', test: /\.css$/, chunks: 'all', // pack all CSS files loaded synchronously or asynchronously into a file named styles. Enforce: true // Ignore the distinction between minSize and maxSize. }}}Copy the code

Webpack and browser caching

  • In the package generated main.xxx.js and vendor.xxx.js, a Runtime.xxx. js is generated because the following is configured.
optimization: {
    runtimeChunk: {
        name: 'runtime'
    }
}
Copy the code

The code associated with the main.js and vendor third-party libraries is called manifest

  • Configure contenthash in Output to help the browser cache.

The code is as follows:

output: {
    filename: '[name].[contenthash].js',
    chunkFilename: '[name].[contenthash].js'
}
Copy the code

Shimming Shim presets dependencies to resolve compatibility issues during packaging.

  • usewebpack.ProvidePluginConfigure. To provide global modules
new webpack.ProvidePlugin({
    $: 'jquery'
})
Copy the code
  • useimports-loaderTo point this in each module to the global variable window, using the example:
module: { rules: [{ test: /\.js$/, exclude: /node_modules/, use: [{ loader: 'babel-loader' }, { loader: 'imports-loader? This =>window' // This can be configured to point to a global variable.}]}]}Copy the code

Packaging line environment

Webpack. Config. Js configuration

const path = require('path') module.exports = { mode: 'production', entry: './src/index.js', // externals: [" lodash "], / / / / the first configuration way externals: {/ / lodash: {/ / root: '_', / / introduced through global scripts, and inject _ in the page for the global variable lodash / / commonjs: External: 'lodash', external: 'lodash', external: 'lodash', external: 'lodash', external: 'lodash', external: 'lodash' path.resolve(__dirname, 'dist'), filename: 'library.js', library: <script SRC ="library"></script> configure root to introduce libraryTarget via root variable: Library,window->window.library,global->global.library to import}}Copy the code

Pwa packaging configuration

  • Http-server generates a server and starts it locally.
  • The purpose of pWA is to have a server accessible for the first time, and to use caching when the server is down.
  • The workbox-webpack-plugin uses PWA
Serviceworker const WorkboxPlugin = require("workbox-webpack-plugin") plugins: [ new WorkboxPlugin.GenerateSW({ clientsClaim: true, skipWaiting: True})], apply serviceworker if (' Serviceworker 'in navigator) {window.addeventListener ('load', () => { navigator.serviceWorker.register('./service-worker.js') .then(registration => { console.log('service-worker registed') }).catch(error => { console.log('service-worker register error') }) }) }Copy the code

This will keep our pages in cache.

Typescript packaging configuration

  • Typescript is a superset of javascript
  • A file that requires additional configuration of tsconfig.json
{"compilerOptions": {"outDir": "./dist", // output directory "module": "es6", // use ES6 "target": "Es5 ", // package the output es5 syntax file code type "allowJs": true // allow the introduction of JS modules in TS}}Copy the code
  • You need to use the external library and implement some error messages that can prompt the external library. We need to import the corresponding TS type file from the external library
  • For example: import _ from ‘lodash’
  • I’m going to introduce @types/ Lodash

WebpackDevServer implements request forwarding

  • In the mode development environment, proxy is configured under devServer for forwarding. However, there is no devServer in the online environment, so it generally does not take effect
Module. exports = {mode: 'development', devServer: {XXX, proxy: {// react/ API ': {// module.exports = {mode: 'development', devServer: {XXX, proxy: { 'http://www.dell-lee.com', // forward the current localhost to this domain pathRewrite: {'header.json': 'demo.json'} // If header.json is not yet developed, you can forward it to the demo.json file. After development, remove this configuration}}}}Copy the code
  • Use secure: false when requesting HTTPS, as shown in the following code:
module.exports = { mode: 'development', devServer: { xxx, proxy: { '/react/api': { target: 'https://www.dell-lee.com', // HTTPS secure is used here: False, // When using HTTPS, secure is configured here because backend servers running over HTTPS with invalid certificates are not accepted by default. pathRewrite: { 'header.json': 'demo.json' } } } } }Copy the code
  • An interception can also be performed using bypass. Such as the following code:
module.exports = { mode: 'development', devServer: { xxx, proxy: { index: '/react/ API ': {target: 'http://www.dell-lee.com', context: / [' auth ', '/ API], / / if there are multiple paths can be treated so bypass: function (the req, res, proxyOptions) {if (the req. Headers. Accept. IndexOf (" HTML ")! == -1) { console.log("Skipping proxy for browser request."); return "/index.html"; }}}, changeOrigin: true // Prevents websites from restricting Origin retweets. Headers: {// The request headers can be forwarded. host: 'www.dell-lee.com', cookie: 'asd' } } } }Copy the code

WebpackDevServer solves the problem of single page application routing

  • Configure the historyApiFallback parameter in devServer
  • DevServer can only be used in a development environment
  • A code example is as follows:
DevServer: {historyApiFallback: true} // Rewrite can be configured as follows: devServer: {historyApiFallback: {rewrites: [{from: /^\/$/, to: '/views/landing.html'}, // To: /views/loading.html {from: /^ // subpage/, to: '/views/subpage.html' }, { from: /./, to: '/views/404.html' } ] } }Copy the code

Configuration of ESLint in WebPack

  • Eslint configurations for quick initialization in projects can be used:npx eslint --init
  • Use the steps to install ESlint-Loader in the project -> install eslint-Loader -> configure overlay to true in devServer -> configure eslint-Loader in module
DevServer: {overlay: true}Copy the code
module: { rules: [{ test: /\.js$/, exclude: /node_modules/, use: ['babel-loader', 'eslint-loader'] // Configure eslint-loader here}}Copy the code
  • The following will automatically fix the code for you
module: { rules: [{ test: /\.js$/, exclude: /node_modules/, use: ['babel-loader', { loader: 'eslint-loader', options: Force: 'pre' // Force eslint to execute first}}]}}Copy the code

Improve webPack packaging speed

  • 1. Update webPack/Node/NPM/YARN to keep up with technical iterations
  • Apply loader to as few modules as possible, such as the following code:
module: { rules: [{ test: /\.js$/, exclude: // node_modules/, // Exclude is used to exclude the code in node_module, because it is already packaged and compiled. Path. resolve(__dirname, '../ SRC ') // set babel-loader to use only SRC folder: [{loader: 'babel-loader'}]}Copy the code
  • 3. Plugins are as lean and reliable as possible
    • It is best to use an official plugin or a community-proven plugin
    • Use the plugin as sparingly as possible
  • 4. Set resolve properly
Module. exports = {resolve: {extensions: ['.js', '.jsx'], // When referencing other components in a page, this configuration helps you find jsx-ending files in that directory first. MainFiles: ['index', 'child'] mainFiles: ['index', 'child'] // Alias: {dellee: path.resolve(__dirname, '.. / SRC /child') // The alias is used here. When referring to the alias delle, it refers to the child directory under SRC. When writing 'import Child from dellee' to import third-party libraries}}}Copy the code

Resolve is useful, but can’t be abused. Configure it properly, otherwise it will slow down the webpack speed.

  • 5. Use DllPlugin to speed up packaging
    • Steps:
    • (1) Use one firstwebpack.dll.js, to bring in third-party plug-ins are loaded and packaged into a xx.dll.js file
    • (2) UseDllPluginTo generate a corresponding manifest.json file that maps to the webpack.dll.js file. So that when we reference the third party module, only use DLL file introduction, only reference once.
    // webpack.dll. Js file const path = require('path'); const webpack = require('webpack'); module.exports = { mode: 'production', entry: { vendors: ['lodash'], react: ['react', 'react-dom'], jquery: ['jquery'] }, output: { filename: '[name].dll.js', path: path.resolve(__dirname, '.. Plugins: [// use Dllplugin new webpack.dllplugin ({name: '[name]', path: path.resolve(__dirname, '../dll/[name].manifest.json'), }) ] }Copy the code
    • (3) Used in the configuration of the projectDllReferencePluginTo generate the xxx.manifest.json file for mapping. Instead of using third-party plug-ins in node_modules, the project can be found in xxx.dll. Js files, which can improve the packaging speed.
    / / webpack.com mon. Js added in the configuration of the plugins: [new AddAssetHtmlWebpackplugin ({filepath: Path. The resolve (__dirname, '.. / DLL/vendors. DLL. Js')}) / / here with the help of AddAssetHtmlWebpackplugin plug-in to global variables vendors mount into the Windows.  new webpack.DllReferencePlugin({ manifest: path.resolve(__dirname, '../dll/vendors.manifest.json') }) ]Copy the code
    • * * * * * * * * * * * * * * * * * * * * * * * So as to make the configuration of the plugin to match this new AddAssetHtmlWebpackplugin and new webpack DllReferencePlugin. You can then use functions for generic processing to make the configuration more flexible.
    // Code example: const plugins = [// here is the fixed plugin new HtmlWebpackPlugin({template: 'src/index.html' }), new CleanWebpackPlugin(['dist'], { root: path.resolve(__dirname, '../') }) ]; // The fs file is introduced through the node module to read the contents of the DLL folder, and then the matching process, so as to achieve more only. const files = fs.readdirSync(path.resolve(__dirname, '.. /dll')); files.forEach(file => { if(/.*\.dll.js/.test(file)) { plugins.push(new AddAssetHtmlWebpackPlugin({ filepath: path.resolve(__dirname, '.. /dll', file) })) } if(/.*\.manifest.json/.test(file)) { plugins.push(new webpack.DllReferencePlugin({ manifest: path.resolve(__dirname, '.. / DLL ', file)}))}}) module.exports = {XXX, plugins,}Copy the code
  • 6. Control package file size
    • Third-party modules that are not needed in the project should be controlled or not brought in using tree-shaking to avoid packaging generated files that are too large.
    • You can also use the splitChunkPlugin to split the code.
  • 7. Webpack is Node based, so it is single-process and we can use itthread-loaderMulti-process packaging, orparaller-webpackMulti-page packaging,happypackAnd so on to carry out multi-process packaging, so as to improve the packaging speed.
  • 8. Use sourceMap wisely, because the more detailed sourceMap is, the slower it will be packaged, so use it wisely, using different configurations for different environments
  • 9. Analyze packaging results based on STATS.
  • 10. The development environment uses in-memory compilation
  • 11. Eliminate useless plug-ins in the development environment

Multi-page WebPack configuration

  • Principle: add multiple entry js files in entry file, usenew HtmlWebpackPluginConfigure the generation of multiple HTML, multi-page packaging process.
// Code examples: Const makePlugins = (configs) => {// This is the default configuration of plugin const plugins = [new CleanWebpackPlugin(['dist'], {root: path.resolve(__dirname, '../') }) ]; // Loop through htmlWebpackplugin to generate different files by getting entry from configs. Object.keys(configs.entry).foreach (item => {plugins.push(new HtmlWebpackPlugin({template: 'src/index.html', filename: `${item}.html`, chunks: ['runtime', 'vendors', item] }) ) }); const files = fs.readdirSync(path.resolve(__dirname, '.. /dll')); files.forEach(file => { if(/.*\.dll.js/.test(file)) { plugins.push(new AddAssetHtmlWebpackPlugin({ filepath: path.resolve(__dirname, '.. /dll', file) })) } if(/.*\.manifest.json/.test(file)) { plugins.push(new webpack.DllReferencePlugin({ manifest: path.resolve(__dirname, '.. /dll', file) })) } }); return plugins; } const configs = {// For every new page used here, a new entry can be added. entry: { index: './src/index.js', list: './src/list.js', detail: './src/detail.js', } } configs.plugins = makePlugins(configs); module.exports = configsCopy the code

Write your own loader

  • 1. When can I write loader by myself
    • (1) Exception capture
    • (2) Loader can be used for internationalization.

The difference between loader and plugin

  • When we need to reference js files or other formats of files, we can use loader to help process this file, help us to process modules
  • Plugin takes effect when we package. For example, htmlWebpackplugin is used when we package to generate an HTML file, and cleanWebpackPlugin is used when we need to clean the folder before packaging
  • Loader is essentially a function, plugin is essentially a class

bail

  • Stop as soon as you encounter an error in the packaging process

pathinfo

  • Some information about the entry will be output in the form of comments.

devtoolModuleFilenameTemplate

  • Help us find the real location of source-map, which helps us tune better

optimization

  • Do some optimization and code compression

runtimeChunk

RuntimeChunk: true // Packs the runtime code into a separate fileCopy the code

vue-cli

  • Vue-based scaffolding tools