webpackWith 5 coming up soon, completely writing an optimized scaffold by hand is an indispensable skill.

  • Writing TimeMay 9, 2019 , webpackversion4.30.0The latest version
  • Want to be reproduced must contact oneself to be reproduced through agree just can be reproduced thank!
  • Put an end to5 minutesLet’s go into the principle first and then write the configuration, that will be much easier.

Implementation requirements:

    • identifyJSXfile
    • tree shakingTree shaker removes useless code
    • PWAFeatures, hot refresh, immediately after installation take over the browser after offline still allows access to the website can also be added from the phone to the desktop for use
    • CSSModularity, not afraid of naming conflicts
    • Little picturesbase64To deal with
    • File suffixes omittedjsx js jsonEtc.
    • Lazy load, load on demand, code segmentation
    • supportless sass stylusSuch as pretreatment
    • code splitingOptimize the loading time of the first screen to prevent a file from being too large
    • Extract the common code and package it into onechunk
    • eachchunkThere is a correspondingchunkhashEach file has a correspondingcontenthashTo facilitate the browser to distinguish between cache
    • Image compression
    • CSSThe compression
    • increaseCSSPrefixes are compatible with various browsers
    • Package output for various different files under the specified folder
    • The cachebabelTo speed up the compilation
    • One for each entry filechunk, packaged out corresponding to a file is alsocode spliting
    • deleteHTMLUnnecessary contents such as comments on files
    • Remove old packaging code with each build
    • willCSSThe files are extracted separately
    • And so on…
    • webpackThe slogan on the Chinese website is: Make everything simple

    Concept:

    In essence,webpackIs a modernJavaScriptStatic module packagers for applications (module bundler). whenwebpackWhen working with an application, it recursively builds a dependency graph (dependency graph), which contains every module your application needs, and then packages all of these modules into one or morebundle.

    Webpack v4.0.0To start, you don’t have to import a configuration file. However, WebPack is still highly configurable. There are four core concepts you need to understand before you begin:

    • The entrance (entry)
    • Output (output)
    • loader
    • Plug-in (plugins)

    This article aims to give a high level overview of these concepts and provide detailed use cases for specific concepts.

    Let’s go over the basics
    WebpackKnowledge, if you are a master, then please ignore these directly to read….

    • The entrance

      • The entry point indicates which module WebPack should use as a starting point for building its internal dependency graph. Once at the entry point, WebPack finds out which modules and libraries are (directly and indirectly) dependent on the entry point.
      • Each dependency is then processed and finally output to calledbundles We will discuss this process in detail in the next section.
      • Can be accessed throughwebpack Configuration in Configuration entryProperty to specify an entry point (or more entry points). The default value is./src.
      • Let’s look at the simplest example of an Entry configuration:

        webpack.config.js
        
        module.exports = {
          entry: './path/to/my/entry/file.js'
        };Copy the code
      • The entry can be an object or a pure array

        entry: {
            app: ['./src/index.js', './src/index.html'],
            vendor: ['react'] 
        },
        entry: ['./src/index.js', './src/index.html'],Copy the code
      • One might say, how do you put the entranceHTMLFile because development mode hot update if not set entry forHTML, so changedHTMLThe content of the file, it’s not going to refresh the page, you have to refresh it manually, so this is the entryHTMLA document, a detail.
    • Exports (output)

      • The Output attribute tells WebPack where to export the bundles it creates and how to name these files, with the default being./dist. Basically, the entire application structure is compiled into a folder in the output path you specify. You can configure these processes by specifying an output field in the configuration:
        webpack.config.js
        
        const path = require('path');
        
        module.exports = {
          entry: './path/to/my/entry/file.js',
          output: {
            path: path.resolve(__dirname, 'dist'),
            filename: 'my-first-webpack.bundle.js'
          }
        };Copy the code

    In the example above, we use the output.filename and output.path attributes to tell the name of the Webpack bundle and where we want the bundle to emit. In case you’re wondering what the path module imported at the top of the code is, it’s a Node.js core module that manipulates file paths.

    • loader

      • Loader enables Webpack to handle non-javascript files (WebPack itself only understands JavaScript). Loader can convert all types of files into valid modules that WebPack can handle, and then you can take advantage of WebPack’s packaging capabilities to process them.
      • In essence, WebPack Loader converts all types of files into modules that the application’s dependency diagram (and ultimately its bundle) can reference directly.
      • Note that loader can import any type of module (such as.css files), which is unique to WebPack and may not be supported by other packers or task executors. We think this language extension is necessary because it allows developers to create more accurate dependency diagrams.
      • At a higher level, loader has two goals in the webpack configuration:
      • The test property identifies the files or files that should be converted by the corresponding loader.
      • The use attribute indicates which loader should be used for conversion.

            webpack.config.js
            
            const path = require('path');
            
            const config = {
              output: {
                filename: 'my-first-webpack.bundle.js'
              },
              module: {
                rules: [
                  { test: /\.txt$/, use: 'raw-loader' }
                ]
              }
            };
            
            module.exports = config;Copy the code
      • Above configuration, on a separate module The rules object defines the rules property, which contains two required properties: test and use. This tells the Webpack compiler (compiler) The following information:
      • “Hey,webpack The compiler, when you encounter “in require()/importStatement is resolved to'.txt'Before you pack it, use itraw-loaderSwitch.”
      • It’s important to remember that inwebpackDefinition in configuration loaderIs defined in module.rulesIn, not rules. However, when the definition is wrong webpack Will give a serious warning. In order for you to benefit from this, if you don’t do it the right way,webpackWill “give a serious warning”
      • loaderThere are more specific configuration properties that we haven’t mentioned yet.
      • Here is a quote from this author’s excellent article, handwritten oneloaderandplugin Write a loader and plugin by hand

    The climax came,webpackCompiler principles, why learn to learn principles first? Because you should at least know what you’re writing about!

    • Webpack packaging principles

      • Identification entry file
      • Identify module dependencies layer by layer. (Commonjs, amdOr es6The import, webpackIt’s analyzed. To get code dependencies)
      • webpackAll you do is analyze the code. Transform code, compile code, output code
      • The result is packaged code
      • All of these arewebpackSome of the basics for understandingwebpackIs very helpful.
    • What is loader?

      • loaderIs a file loader, can load resource files, and perform some processing on these files, such as compilation, compression, and finally packaged together into the specified file
      • You can use more than one fileloader.loaderThe order of execution is the reverse of its own order, that is, the last oneloaderExecute first, number oneloaderExecute last.
      • The first to executeloaderReceive source file contents as parameters, othersloaderReceived from the previous executionloaderReturns the value of Last executedloaderThis module will be returnedJavaScriptThe source code
      • When using multipleloaderIf you want to modify a file while processing itoutputPathOutput directory, then please at the topOptions in the loader
    • What is a plugin?

      • inWebpackMany events are broadcast during the runtime lifecycle,PluginYou can listen for these events and change the output when appropriate through the API provided by Webpack.
      • The plugin and loaderWhat is the difference between?
      • forloader, it is A converter to compile file A into file B. Here, the operation is the file, such as a.CSS or A.ess into B.CS, simple file conversion process
      • pluginIt’s an extender, it’s enrichedwepackIn itself, for isloaderAfter the end,webpackThe whole process of packaging, which does not operate on files directly, works based on an event mechanism that listenswebpackSome nodes in the packaging process perform a wide range of tasks.
    • The operation of the webpack

      • webpackAfter it is started, it is executed first during the reading of the configurationnew MyPlugin(options) Initialize a MyPlugin to get an example. Is called after the Compiler object has been initialized myPlugin.apply(compiler)Pass in the plug-in instance compilerObject. The plug-in instance is being retrievedcompilerAfter the object can be passedcompiler.plugin(Event name, callback function) onWebpack An event broadcast. And can be accessed through compiler Object to operate webpack
      • You might look at this and askcompilerIs what,compilationIs what?
      • CompilerThe Webpack object contains all configuration information for the Webpack environment, includingOptions, loaders, pluginsThis information, which is instantiated when Webpack starts, is globally unique and can simply be understood asWebpackInstance;
      • Compilation Object contains the current module resources, build resources, changing files, and so on. whenWebpackRun in development mode whenever a file change is detected, a new oneCompilationWill be created.Compilation Object also provides many event callbacks for plug-ins to extend. throughCompilationYou can also read it CompilerObject.
      • CompilerCompilationThe difference lies in:
      • CompilerRepresents the whole Webpack Lifecycle from startup to shutdown, while Compilation It just represents a new compilation.
    • Flow of events

      • webpack through Tapable To organize this complex production line.
      • webpackThe event flow mechanism ensures the order of plug-ins and makes the whole system expand well.
      • webpackThe event flow mechanism applies the observer pattern, andThe EventEmitter Node. JsVery similar.

    Let’s start the configuration of the development environment:

    • Entrance setting:

      • Set up the APP, several entry files, which will eventually be split into severalchunk
      • Configure in the entryvendor, you cancode spliting And finally extract these common reusable codes into onechunkPack them separately
      • To be in development modeHMTLFiles are also hot updated and need to be addedindex.htmlIs the entry file
    Entry: {app: ['./ SRC /index.js', './ SRC /index.html'], vendor: ['react'] // Redux react-redux better scrollCopy the code
    • The output export

      • webpackBased on theNode.jsThe environment is running and can be usedNode.jstheAPI.pathThe moduleresolvemethods
      • The output of theJSFile, joincontenthashFlag to allow the browser to cache files between versions.
    output: { filename: '[name].[contenthash:8].js', path: resolve(__dirname, '.. /dist') },Copy the code
    • mode: 'development'Mode selection, here directly set to development mode, start from development mode.
    • Add config to resolve all file suffixes without js JSX JSON

      resolve: {
          extensions: [".js", ".json", ".jsx"]
      }Copy the code
    • Add plugin hot update plugin and HTMl-webpack-plugin

         
         const HtmlWebpackPlugin = require('html-webpack-plugin')
         const webpack = require('webpack')
         new HtmlWebpackPlugin({
                 template: './src/index.html'
             }),
         new webpack.HotModuleReplacementPlugin(),Copy the code
    • Add Babel-Loader and Babel Preset, which parses JSX ES6 syntax

      • @babel/preset-reactparsingJSX grammar
      • @babel/preset-envparsinges6grammar
      • @babel/plugin-syntax-dynamic-importparsingreact-loadabletheimportLoad on demand, attachedcode splitingfunction
        {
            test: /\.(js|jsx)$/,
            use:
            {
                loader: 'babel-loader',
                options: {
                    presets: ["@babel/preset-react", ["@babel/preset-env", { "modules": false }]],
                    plugins: ["@babel/plugin-syntax-dynamic-import"]
                         },
    
            }
       },
      Copy the code
    • ReactOn demand, with code splitting, each on demand component is packaged into a separate file
    import React from 'react' import loadable from 'react-loadable' import Loading from '.. /loading' const LoadableComponent = loadable({ loader: () => import('.. /Test/index.jsx'), loading: Loading, }); Class Assets extends React.Component {render() {return (<div> <div> this is about to load on demand </div> </div>)}} class Assets extends React.Component {render() {return (<div> <div>)}} export default AssetsCopy the code
    • joinhtml-loaderidentifyhtmlfile
        {
        test: /\.(html)$/,
        loader: 'html-loader'
        }Copy the code
    • joineslint-loader
            {
            enforce:'pre',
            test:/\.js$/,
            exclude:/node_modules/,
            include:resolve(__dirname,'/src/js'),
            loader:'eslint-loader'
            }Copy the code
    • The development mode termination code is shown below
    const { resolve } = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin') const webpack = require('webpack') const WorkboxPlugin = require('workbox-webpack-plugin') module.exports = { entry: { app: ['./src/index.js', './src/index.html'], vendor: ['react', ] }, output: { filename: '[name].[hash:8].js', path: resolve(__dirname, '.. /build') }, module: { rules: [ { enforce:'pre', test:/\.js$/, exclude:/node_modules/, include:resolve(__dirname,'/src/js'), loader:'eslint-loader' }, { oneOf: [{ test: /\.(html)$/, loader: 'html-loader' }, { test: /\.(js|jsx)$/, use: { loader: 'babel-loader', options: { presets: ["@babel/preset-react", ["@babel/preset-env", { "modules": false }]], plugins: ["@babel/plugin-syntax-dynamic-import"] }, } }, { test: /\.(less)$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader', options: { modules: true, localIdentName: '[local]--[hash:base64:5]' } }, { loader: 'less-loader' } ] }, { test: /\.(jpg|jpeg|bmp|svg|png|webp|gif)$/, loader: 'url-loader', options: { limit: 8 * 1024, name: '[name].[hash:8].[ext]', } }, { exclude: /\.(js|json|less|css|jsx)$/, loader: 'file-loader', options: { outputPath: 'media/', name: '[name].[hash].[ext]' } } ] }] }, plugins: [ new HtmlWebpackPlugin({ template: ' '. / SRC/index. HTML}), new webpack. HotModuleReplacementPlugin (), new webpack. NamedModulesPlugin (), / / packaging when can see the file name of the plugin, mode: 'development', devServer: { contentBase: '.. /build', open: true, port: 3000, hot: true }, resolve: { extensions: [".js", ".json", ".jsx"] } }Copy the code

    Must knowwebpackHot update principle:

    • Hot updates to Webpack are also known as Hot Module Replacement, or HMR. This mechanism allows you to replace the old module with the new one without refreshing the browser.

    • The first thing to know is that both the server and client side do the processing

      • Step one, inThe watch webpackIn this mode, a file in the file system is modified.webpackListen for file changes, recompile and package the module according to the configuration file, and pass the packaged code through a simple JavaScript Objects are stored in memory.
      • The second step is to webpack-dev-server webpackInterface interaction between, and in this step, mainlydev-server The middlewareWebpack - dev - middleware and webpackThe interaction between,webpack-dev-middleware call webpackExposed apis monitor code changes and tell webpackPackage the code into memory.
      • The third step is towebpack-dev-serverA monitoring of file changes, which, unlike the first step, does not monitor code changes for repackaging. When we configure it in the configuration filedevServer.watchContentBaseWhen true, the Server listens for changes in the static files in these configuration folders and tells the browser to live reload the application. Notice that this is browser refresh, and HMR are two different things.
      • Step four is also webpack-dev-serverThis step is mainly through sockJS (webpack-dev-server dependency) to establish a websocket long connection between the browser side and the server side, webpack compilation and packaging of each stage of the state information to inform the browser side, It also includes information that the Server listens for static file changes in step 3. The browser performs different operations based on these socket messages. Of course, the most important information passed by the server is the hash value of the new module, and the subsequent steps use this hash value to perform module hot replacement.
      • webpack-dev-server/clientThe end cannot request the updated code, nor does it perform the hot module operation, handing the work back to the endWebpack webpack/hot/dev server. -Work is based on webpack-dev-server/client The messages that were sent to it and dev-serverConfiguration determines whether to refresh the browser or hot update the module. Of course, if you just refresh the browser, there are no further steps.
      • HotModuleReplacement.runtime Is the backbone of the client HMR, which receives the new module passed to it in the previous stephash Value, it passesJsonpMainTemplate.runtime Send an Ajax request to the server, and the server returns one jsonthejsonContains the hash values of all modules to be updated. After obtaining the updated list, the module will request jSONP again to get the latest module code. These are steps 7, 8 and 9 in the figure above.
      • Step 10 is the key step that determines the success of HMR. In this step,HotModulePluginThe old and new modules will be compared to decide whether to update the modules. After the decision is made to update the modules, the dependencies between the modules will be checked and the dependencies between the modules will be updated at the same time.
      • The last step, whenHMR After failure, fall back tolive reloadAction, that is, a browser refresh to get the latest packaging code.
      • Reference article Webpack interview question – Tencent cloud

    Officially start production:

    • Join the WorkboxPlugin, PWA’s plugin

      • pwaThis technology is a bit of a work in progress, with its life cycle and the side effects of hot updates in browsers. You can refer to BaidulavasFramework development history ~
    const WorkboxPlugin = require('workbox-webpack-plugin') new WorkboxPlugin.GenerateSW({ clientsClaim: ImportWorkboxFrom: 'local', include: [/\.js$/, /\.css$/, /\.html$/,/\.jpg/,/\.jpeg/,/\.svg/,/\.webp/,/\.png/], }),Copy the code
    • Add each time the package output file is emptied of the last package file plug-in
        const CleanWebpackPlugin = require('clean-webpack-plugin')
        
        new CleanWebpackPlugin()Copy the code
    • joincode splitingThe code segment
    Optimization: {runtimeChunk:true, // If this is set to true, a chunk is a file, and a chunk is a chunk with chunks, CSS images, etc. 'all' // chunk of default entry will not be split, set to 'all', can be split, an entry 'JS', // package to generate a separate file}}Copy the code
    • Add separate extractionCSSOf the fileloaderAnd plug-ins
    const MiniCssExtractPlugin = require('mini-css-extract-plugin')
    
        {
            test: /\.(less)$/,
            use: [
                MiniCssExtractPlugin.loader,
                {
                    loader: 'css-loader', options: {
                        modules: true,
                        localIdentName: '[local]--[hash:base64:5]'
                    }
                },
                {loader:'postcss-loader'},
                { loader: 'less-loader' }
            ]
        }
        
         new MiniCssExtractPlugin({
                filename:'[name].[contenthash:8].css'
            }),
    Copy the code
    • Join the compressioncssThe plug-in
        const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
        new OptimizeCssAssetsWebpackPlugin({
                    cssProcessPluginOptions:{
                        preset:['default',{discardComments: {removeAll:true} }]
                    }
                }),Copy the code
    • killhtmlSome useless code
        new HtmlWebpackPlugin({
            template: './src/index.html',
            minify: {
                removeComments: true,  
                collapseWhitespace: true,  
                removeRedundantAttributes: true,
                useShortDoctype: true, 
                removeEmptyAttributes: true,
                removeStyleLinkTypeAttributes: true,
                keepClosingSlash: true, 
                minifyJS: true,
                minifyCSS: true, 
                minifyURLs: true, 
             }
    }),Copy the code
    • Add image compression
    { test: /\.(jpg|jpeg|bmp|svg|png|webp|gif)$/, use:[ {loader: 'url-loader', options: { limit: 8 * 1024, name: '[name].[hash:8].[ext]', outputPath:'/img' }}, { loader: 'img-loader', options: { plugins: [ require('imagemin-gifsicle')({ interlaced: false }), require('imagemin-mozjpeg')({ progressive: true, arithmetic: False}), require('imagemin-pngquant')({Floyd: 0.5, speed: 2}), require('imagemin-svgo')({plugins: [{removeTitle: true }, { convertPathData: false } ] }) ] } } ] }Copy the code
    • joinfile-loaderPackage some files and export them to a fixed directory
    {
                    exclude: /\.(js|json|less|css|jsx)$/,
                    loader: 'file-loader',
                    options: {
                        outputPath: 'media/',
                        name: '[name].[contenthash:8].[ext]'
                    }
                }
                Copy the code

    There are some notes may not be detailed, the code is their own little bit of writing, tried, certainly no problem

    • Required dependency
    {" name ":" webpack ", "version" : "1.0.0", "main" : "index. Js", "license" : "MIT", "dependencies" : {" @ Babel/core ": "^ 7.4.4 @", "Babel/preset - env" : "^ 7.4.4", "@ Babel/preset - react" : "^ 7.0.0", "autoprefixer" : "^ 9.5.1", "Babel - loader" : "^ 8.0.5 clean - webpack -", "plugins" : "^ 2.0.2", "CSS - loader" : "^ 2.1.1", "eslint" : "^ 5.16.0", "eslint - loader" : "^ 2.1.2 file -", "loader" : "^ 3.0.1", "HTML - loader" : "^ 0.5.5", "HTML - webpack - plugin" : "^ 3.2.0", "imagemin" : "^ 6.1.0 imagemin - gifsicle", "" :" ^ the 6.0.1 ", "imagemin - mozjpeg" : "^ 8.0.0", "imagemin - pngquant" : "^ 7.0.0", "imagemin - svgo" : "^ 7.0.0", "img - loader" : "^ 3.0.1", "less" : "^ 3.9.0", "less - loader" : "^ 5.0.0", "mini - CSS - extract - the plugin" : "^ 0.6.0", "optimize - CSS - assets - webpack - plugin" : "^ 5.0.1", "postcss - loader" : "^ 3.0.0", "react" : "^ 16.8.6", "the react - dom" : "^ 16.8.6", "the react - loadable" : "^ 5.5.0", "the react - redux" : "^ 7.0.3", "style - loader" : "^ 0.23.1", "url - loader" : "^ 1.1.2 webpack", ""," ^ 4.30.0 ", "webpack - cli" : "^ 3.3.2 rainfall distribution on 10-12", "webpack - dev - server" : "^ 3.3.1", "workbox - webpack - plugin" : "^ 4.3.1"}, "scripts" : {" start ":" webpack dev - server -- config. / config/webpack. Dev. Js ", "dev" : "webpack-dev-server --config ./config/webpack.dev.js", "build": "Webpack --config./config/webpack.prod.js"}, "devDependencies": {"@babel/plugin-syntax-dynamic-import": "^7.2.0"}Copy the code

    The whole project andwebpackSource code address:Source code address ah see pro

    Passing by the small partner trouble point a praise to a star, write very hard !!!!