This is the 8th day of my participation in the August More Text Challenge. For details, see:August is more challenging

Modular development

  • Modular development is the most important front-end development paradigm

The evolution of modularity

  • Stage1 – The way files are divided

    In the original module system, each function and different status data were stored in separate files. Import at global scope.

    Disadvantages: Fouling global scope, naming conflicts, unable to manage module dependencies

    Early modularity was all about convention, and once you get up to volume, you’ll expose a lot of problems.

  • Stage2 – Namespace mode

    Based on Stage1, wrap an object and add a namespace to each module

    Disadvantages: There is no concept of privatization, members in modules can still be accessed or modified, and dependencies between modules remain unresolved.

  • Stage3 – IIFE

    Use self-executing functions to provide private space. For members that want to be exposed externally, do so by mounting them into a global object. Ensures that the module is privatized.

    // Module a related status data and functions; (function () {
      var name = 'module-a'
      
      function method1 () {
        console.log(name + '#method1')}function method2 () {
        console.log(name + '#method2')}window.moduleA = {
        method1: method1,
        method2: method2
      }
    })()
    Copy the code

The emergence of modularity specifications

  • Unify differences between developers who implement modularity. Modularity needs to be regulated to specify how modularity is implemented.
  • Some basic common code is needed to automatically load the code into modules.

This is the modularity standard + module loader (the basic library that automatically loads modularity)

Commonjs module

  • A file is a module
  • Each module has a separate scope
  • Exports members through module.exports
  • The modules are loaded through the require function

The coommonjs convention is to load modules synchronously. The execution mechanism of Node is to load modules at startup. During the execution process, modules are not required to be loaded, but only used.

If the CommonJS specification is used on the browser side, it will inevitably lead to inefficiency, with a large number of synchronous request patterns every time the page loads.

Module specification designed for use on the browser side

AMD (Asynchronous Module Definition). Asynchronous module definition specification

The famous require.js implements the AMD specification.

  • The define function is used to define a module in require.js. The name of the argument 2.array. Declare the dependencies of the module. 3. Functions whose arguments correspond to the dependencies of the module provide private space for the module. If you need to expose members, use the return method.
  • Require,.js specifies the introduction of a module, using the Require function, the internal will automatically create a script tag to send the script file request, and execute the corresponding script code.

Disadvantages:

  • AMD is relatively complex to use.

  • If the module is partitioned too carefully, the JS file will be requested frequently.

Sea-.js + CMD is also a module specification for browsers.

Standard Specification for modularity (Best practice)

  • The CommonJS specification is used in nodeJS environments
  • Using the ES Module specification in the browser environment (implementing the modularity specification at the language level)

ES Module

ES Module Basic features

  • Strict mode is automatically adopted
  • Each ESM module is a separate private scope
  • The ESM requests external JS modules through CORS.
    • The external JS of the request needs to support spanning.
  • The ESM script tag delays the execution of the script.

ES Module imports and exports

  • If you import a Module in the form of an ES Module, the Module has a private scope and the variables in it are not accessible.

    In other words, if you want to use the specification, the specification must comply with it. If you import the module (js file) in the form of esModule, then the JS file will be modularized when you use it.

// module.js
// export var name = 'foo module'

// export function hello() {
// console.log('hello')
// }

// export class Person {

// }

var name = 'foo module'

function hello() {
    console.log('hello')}class Person {}var obj = {
    a: 1
}

setTimeout(() = > {
    console.log(obj) // a = 2
}, 1000);
// You can also use export to export an object, at the end of the module, in a concentrated export
// export {
// name,
// hello,
// Person
// }

// You can also use an alias, or you can use an alias when exporting
// Note: this is a syntax, not a form of exporting an object literal
export {
    name as fooName,
    hello as fooHello,
    obj
}

// This is an exported literal
// export default { name, hello }
Copy the code
// app.js
// Import a reference to the corresponding variable in the module instead of copying a value. And the exported variable is declared as const.
import { fooName, obj } from './module.js'
obj.a = 2
console.log(fooName)
Copy the code

The import of grammar

  • In CommonJS, js after require(‘./app’) can be omitted

    • In the commonjsrequire('./utils')It will automatically load index.js under utils.
  • Import {name} from ‘./app.js’ in ESModule is not omitted

    • Import {toLoweCase} from ‘./utils/index.js’ in ESModule is not omitted.

    • The import syntax can be used directly with modules on CND. Such as

      import {name} from 'http://localhost:3000/index.js'

  • Import ‘./module.js’ loads the module, but does not extract it.

  • import * as mod from './module.js'

    • You can use the mod to get all exported members.
  • If such a situation occurs, the module path we import is known at run time.

    We might as well:var modulePath = './module.js'
    import { name } from modulePath // from a variableWe might as well:if(true) {
      import { name } from './module.js' // This is not allowed. The import keyword must be in the outermost scope of the module
    }
    // The right approach: import modules dynamically. The import function can be called anywhere.
    import('./module.js').then(data= > console.log(data)) // Data is the member of the export
    Copy the code
  • If such a situation occurs, there are both export and export default in the same module

    export {
        name as fooName
    }
    
    export default {
        a: 1
    }
    // 
    import { name,a } from './module.js' // error The requested module './module.js' does not provide an export named 'a'The {xx, xx} syntax supports onlyexportIt's not deconstruction, it's just withexportA grammatical correspondenceimport xx from './module.js'This syntax is only supportedexport defaultbutexport defaultIs alsoexportBut it's derived fromdefault, butdefaultIs a keyword, so we can do thisimport { name, default as obj} from './module.js' // This will export everythingorimport obj, {name} from './module.js' // This can also be all exported
    Copy the code

The export of grammar

  • The export syntax has a special use

    export { name, foo } from './module.js'
    export { a, b } from './index.js'
    // This syntax can be used as a collection point for files that are imported and exported in this module, such as index.js
    Copy the code

Ployfill for ESModule

ESModule support in NodeJS

This feature is experimental and should not be used in a production environment

  • Change the js file suffix to MJS, node xx.mjs is executed as an ESM module.

  • Add node –experimental-modules index.mjs when running the node command

    // index.mjs
    import { foo, bar } from './module.mjs'
    import fs from 'fs'
    fs.writeFileSync('./foo.txt'.'write a string to foo.txt')
    
    console.log(foo, bar)
    
    // module.mjs
    export var foo = 'foo'
    export var bar = 'bar'
    Copy the code
  • In nodeJS, the third party exports a default member through export Default and then uses the default member to click on the method, while in the built-in module for convenience. Each method is exported. So you can use {functionName} to do this.

ESModule with commonjs

Use of ESModule with CommonJS in nodeJS environment

  • The COMMONJS module can be imported into the ESM
  • ESM modules cannot be imported into CommonJS
  • Commonjs always exports only one default member
  • Note that import is not deconstructing the exported object

New ESM features are used in nodeJS

  • Change type to Module in package.json and all files in the project will be executed as ESM modules by default. You don’t have to change the file name extension to MJS. If you want to use the CommonJS specification in your project, just change the file name suffix to CJS.

Some of the new features that are not supported by the NodeJS environment can be converted to syntax supported by the current runtime environment using Babel.

Modular packaging tools

  • The ES Module is incompatible with the environment
    • New feature code compilation
  • More files are divided by modularization, and network requests are frequent
    • Modular JS packaging
  • All front-end resources need to be modular
    • Different types of resource modules are supported

webpack

Module packer

: : The scattered module code is packaged into the same JS file through Webpack. For the problem of environment compatibility in the code, it can be converted by the module loader. Webpack can also split the code. The code in the application is packaged according to the need (packaging on demand), to achieve progressive loading. This solves the problem of files that are too fragmented or too large. Webpack loads any type of file in a modular way (import ‘./index.css’).

Webpack addresses the modularity of the front end as a whole, not just JavaScript.

Webpack configuration

  • Webpack can be zero-configured. The default is SRC /index.js –> dist/main.js

  • Webpack treats all modules it encounters as if they were JavaScript

    js file  --> default loader
    other file --> other loader 
    Copy the code
  • Understanding the ideas of new things is the breakthrough, being able to understand why new things are designed the way they are. Why does WebPack advocate that any resource module can be introduced in JS?

  • Loader loader

    • The loader is used to convert other files into JS modules. The other file is tiled to a string and is processed differently depending on the loader. For example, csS-loader +style-loader converts the content of the CSS file into a string, and then creates a style tag to insert into the page using a style-loader.
    • Loader is the core of webPack’s entire front-end modularity
    • Any type of resources can be loaded by loader.

publicPath

Webpack-packed modules are placed in the output directory by default.

  • PublicPath is the url of the resource referenced in the runtime browser with publicPath as its prefix.
  • The default is the empty string “”, which represents the root directory of the web site
  • There is a/at the end of the publicPath value. This/cannot be omitted because it is the form of path concatenation
import icon from './icon.png'
// If there is no publicPath, icon is './[hash].png'
// icon = publicPath+ './[hahs].png'
Copy the code
  • Webpack-dev-server will also default frompublicPathAs a benchmark, you use it to decide in which directory to enable the service to access the files that webPack outputs.

Data URLs and url – loader

  • File-loader is used to copy physical files from the server and pull files in the specified directory

  • You can also represent a file in the form of a Data Url. Base64, the text in the URL already contains the contents of the file, which means you can get the text without sending any HTTP requests.

    data: text/html; Charset = utF-8,<h1> HTML content</h1Copy the code
  • Smaller files use Data URLs to reduce the number of requests

  • Large files are extracted and stored separately to improve the loading speed

    {
      test: /\.png$/.// use: 'url-loader'
        use: {
          loader: 'url-loader'.options: {
              // Files larger than 10KB are also packaged using a file-loader. If we use this method, we still need to install file-loaders
              limit: 10 * 1024 // 10kb}}}Copy the code

Classification of common loaders

  • Compile conversion class

    The resource file is converted to JavaScript code. For example, CSS – loader

  • File operation class

    Resource files will be copied and exported to the file access path. file-loader

  • Code check class

    Unified code style and code quality ESLint-Loader

Webpack and es 2015

  • Webpack automatically handles import syntax and export/export Default syntax. This is because module packaging is required, so handle the import and export and convert them accordingly. That is, webpack provides the base code for impot… The syntax is transformed

    yarn add babel-loader @babel/core @babel/preset-env --dev
    Copy the code
  • Webpack is just a packaging tool, a packaging platform.

  • Loaders can be used to compile the transformation code

How WebPack loads resources (how it triggers packaging)

  • Import declarations follow the ES Modules standard

  • Follow the Commonjs require function

    const name = require('./heading').default
    Copy the code
  • Follow AMD standard define function and require function

Do not mix them, they will reduce the maintainability of the project

  • Non-javascript code loaded by the loader also triggers resource loading (packaging)

    • The loader that handles the style, the @import directive in the style code, and the URL function

      When processing CSS files, we use csS-Loader, which will package the path it imported as a new module if it finds @import syntax or URL syntax. For example, background-image: url(background.png); Webpack finds the.png file and sends it to url-Loader for processing. Such as @ import url (reset. CSS); Webpack finds the.css file, triggers the resource load, and then passes the file to the CSS-Loader for processing.Copy the code
    • The loader that handles HTML,

      • By default, only the SRC attribute of the image tag in the HTML code is used
      • Additional configuration is required if additional configuration is required.
      // Returns a string
      import footerHtml from './footer.html' // Use the html-loader for processing
      document.write(footerHtml)
      Copy the code

Webpack and gulp

Webpack supports commonJS and ESM modularity specifications, which trigger packaging. Gulp does not support these modularity specifications because gulp does not provide the underlying code to support the modularity specifications.

How WebPack results work

Putting all modules in the same file provides the base code to keep the relationships between modules as they are.

All modules are treated as members of an array parameter of a giant anonymous function. Each member of the array is a function, which means webpack treats each module as a function. To maintain the privatization of modules. Starting with the first entry argument, only functions with subscript 0 will be executed first. Each module corresponds to a subscript, and WebPack handles the relationships between modules at compile time. For example, A.js import B.JS. If b.js is subscript 3, then __webpack__.require(3) in a.js is compiled. This is how WebPack maintains the relationships between modules. Webpack subscripts an array of functions in the order in which modules were imported. At compile time, it writes the subscripts of dead modules. This is how relationships between modules are maintained.

  • Webpack provides the base code to implement import and export/export default for modules

How Loader works in WebPack

  • Each loader needs to export a function
    • The result of the function is executed as JavaScript code (which is placed in the body of each module’s function), so the function must return standard executable JavaScript code.
  • The input is what needs to be parsed
  • The output is the result of the processing
1.Multiple Loaders can be used for the same resource in sequence2.Works when the module is loadedCopy the code

How plugins work in WebPack

Loader focuses on loading resource modules and packaging the whole module

Webpack enhances WebPack automation

Plugin’s ability to clean up packaged directories, copy resource files, compress output code, and more.

There are hundreds of plugins available in the community, and we can go to Github and search for them by keyword when we need them.

Webpack’s plug-in mechanism is implemented by the hook mechanism. Similar to events in the Web, there are many links in the working process of the plug-in. To facilitate the extension of the plug-in, WebPack mounts hooks to each link, so that the operation and development of the plug-in is to extend the capabilities in the hook.

The plugin must be either a function or an object containing the apply method.

Plugins are implemented by extending functions within lifecycle hooks.

Digression: The question of the path

Html-webpack-plugin and publicPath are related to paths

The resource path in the HTML page is automatically injected with the value of filename in the output. The value of filename in output. /backend/js/app.11c8b942e5dd4b3a51b5.js? 2C61C09c3e5bFF69e658 is automatically injected into index.html as SRC /href, but the packaging location is determined by path and filename together, that is, the result of filename needs to be set to the server as the root path of the project. Because only the root path can find it. If publicPath is set, all static resource paths will be prefixed with the publicPath publicPath. (No directory is generated, just add the value of publicPath before the imported path)// Set publicPath: '/ ABC '
<script src=/abc/backend/js/app.57e28a966ab9582ff286.js? 1dcc397cc95f5934ef81></script> </script> index.html path is determined by filename However, the path of the resource address in the code is determined by filename+publicPath. For loaders, some loaders have their own publiPath, but you can also set filename to replace the publicPath once and for allCopy the code

SourceMap

  • Sourcemap addresses issues where the run-time code is inconsistent with the development-time code, causing debugging to fail and error messages to fail to locate.

If you need to debug jquery.js, you need to add it to the last line of the imported jquery.min.js

/ / # sourceMappingURL = jquery – 3.4.1 track. Min. The map

Tell the file to find jquery-3.4.1.min.map. This file records the mapping between the code after the transformation and the code before the transformation.

Currently, There are 12 implementations of WebPack’s sourcemap style support, each with varying levels of efficiency and effectiveness.

  • The eval mode

    eval('console.log(123)')  // Vm122:1 runs on a temporary VM.
    eval('console.log(123) //# sourceURL=./foo/bar.js') //./foo/bar.js:1./foo/bar.js
    // Use the sourceURL to specify the runtime name or path.
    Copy the code

    devtools: //# sourceURL=webpack:///./ SRC /main.js? To mark the file path. Represents that the module only wants the path of the source file. The builds are the fastest, but the results are mediocre. You can only locate which file has the problem. No source map will be generated

    Devtools: eval-source-map, which also uses the eval function to execute module code. In addition to helping us locate the problem file, we can also determine the row and column information. Compared with eval, the generated source map introduced in the form of dataURL is generated inside the generated JS. The sourcemap is Babel converted, not the original.

    Cheap-eval-source-map devtools: cheap-eval-source-map, which adds a cheap version to the previous eval-source-map. Compare this to the previous information that can only locate rows, but not columns. But the build speed has accelerated. The principle of source map is the same as above

    Cheap-modol-eval-source-map, rather than cheap-eval-source-map, maps the actual source code, not the compiled one. The xxx.js.map file is generated. Other pain cheap-eval-source-map

    The inline-source-map has the same effect as the source map, but the.js.map file is placed in the last line of the compiled file as a dataURL. Import with #sourceMappingURL. The normal one is to generate.map.js files

    Hidd-source-map: The sourcemap file is generated during the build process. Sourcemap is not commented into the code. This sourcemap style is usually used when developing third-party packages.

    Nosource-source-map, which allows you to see the location of the error but not the source code, provides the location of the error but does not show it to you. This is a way to prevent source code exposure in a production environment.

  • Select the appropriate sourcemap

    • In a development environment: cheap-mod-eval-source-map.

      Reasons for choice:

      1. My code is no more than 80 characters per line, and I only need to provide line information.
      2. My code is quite different after being converted by loader.
      3. It doesn’t matter if the first packing is slow, rewriting is relatively fast.
    • In a production environment: None

      1. Source Map exposes the source code
      2. Debugging is a development phase.
    • In a production environment: nosource-source-map

      • With little information about the code itself, choosing nosource-source-map can locate the error without exposing the source code.

Webpack development experience issues

  • Watch just compiles automatically, but it doesn’t automatically refresh the browser.
  • The browserSync listener file also automatically refreshes the browser. The idea is that WebPack writes the compiled file to disk, and bs detects data changes at a specific location on disk, reads the file from disk, and maps it to the browser.
  • Webpack devServe solves all of these problems. Webpack detects file changes, devServer puts the packaged results into memory, and the internal devServer reads the files from memory and sends them to the browser. Eliminates many unnecessary disk read and write operations. Automatic packaging automatic refresh browser way. But all temporary operational state in the page is lost.
  • The copy-webpack-plugin is used to copy resources that do not need to be built. It is best not to use this plugin during development because configuration tasks are frequently performed during development. If you want to use these unpackaged files during development, you need to specify the static resource directory in webpack-dev-server using contentBase, which can be either a string or an array.
HMR

One of the most powerful features in WebPack, and one of the most popular, greatly improves developer productivity.

  • Hot swap >>> In a running machine, it is possible to temporarily plug and remove other devices without affecting the normal operation of the machine, and the plugged and removed devices can work immediately. For example, the use interface.

  • Module hot replacement

    A module can be replaced in real time during the running of an application without affecting the running status of the application. Hot replacement only replaces the modified modules to the application in real time, without the need to completely refresh the application.

    • Hot updates can hot update not only text files, but other types of files as well.
  • Open the HMR

  • HMR has been integrated into Webpack-dev-serve, using webpack-dev-serve –hot to start hot updates.

    • We found that with hot update enabled, only the CSS works out of the box, and the JS changes still refresh the page. This is because different modules have different logic, and different logic leads to different processing processes. Each JS file needs to handle the hot update of the JS file separately for the js file (according to the logic of the page). Webpack has no way to provide a universal replacement, but vue-CLI or creant-React-app scaffolds can do HMR because they are frameworks, each of which meets certain rules, and the framework inherits HMR hot mode replacement internally.
  • So how do you provide HMR for each JS separately? Use the module.hot.accept provided by WebPack (file path, () => {// hot replace logic})

if (module.hot) {
  let lastEditor = editor
  module.hot.accept('./editor'.() = > {
    // console.log(' Editor module updated, need to handle hot replacement logic here manually ')
    // console.log(createEditor)

    const value = lastEditor.innerHTML
    document.body.removeChild(lastEditor)
    const newEditor = createEditor()
    newEditor.innerHTML = value
    document.body.appendChild(newEditor)
    lastEditor = newEditor
  })
	// The HMR of the picture
  module.hot.accept('./better.png'.() = > {
    img.src = background
    console.log(background)
  })
}
Copy the code
  • Problem: If we use hot: true to enable hot mode replacement, if the replacement fails, such as an error in the code, then we fall back on the HMR setting using automatic refreshHotOnly: true // Use HMR only, no fallback to live reloading.

webpack.DefinePlugin

  • This is to inject global variables into the project. Key: value This value must be a JS code fragment.
new webpack.DefinePlugin({
  // The value requires a code snippet
  API_BASE_URL: JSON.stringify('https://api.example.com')})Copy the code

tree-shaking

To shake the tree is to shake the dead-code out of the code. Mode: production. Tree shaking is automatically enabled.

Realization of Tree-shaking

optimization: {
  usedExports: true.// Mark the dead leaves
  minimize: true	// Be responsible for shaking off the marked dead leaves
}
Copy the code
  • The test tree – shaking
let foo = () = > {
    let x = 1
    if (false) {
        console.log('never readched')}let a = 3
    return a
}

let baz = () = > {
    var x = 'baz is running'
    console.log(x)
    function unused () {
        return 5
    }
    return x
    let c = x + 3
    return c
}

module.exports = {  // CommonJS module specification export
    baz
}
export { // ESM module specification export
	baz 
} 
Copy the code
  • The result of the package
EsModule specifies packaged modules ([function (e, n, r) {
        "use strict";
        r.r(n);
        var t;
        t = "baz is running".console.log(t),
            console.log("main.js running")}]); Commonjs specification packaged modules ([function (e, n, t) {(0, t(1).baz)(), console.log("main.js running")},function (e, n, t) {
        e.exports = {
            baz: function () {
                var e = "baz is running";
                return console.log(e),
                    e
            }
        }
    }
]);
Copy the code
  • Why do you need the esModule specification to do tree-shaking
1.ES6's module introduction is statically analyzed, so it is possible to determine exactly what code has been loaded at compile time.2.Analyze the program flow to determine which variables are not being used, referenced, and then delete the code.Copy the code

Scope Scope increased

Merge module functions

  • Enabled to merge module functions, instead of one function per module, all modules are put into one function.
    • Combine all modules into one function whenever possible.
    • It not only improves the operation efficiency, but also reduces the volume of output code.
optimization: {
  usedExports: true.// Mark the dead leaves
  minimize: true.// Be responsible for shaking off the marked dead leaves
  concatenateModules: true. // Enable the Scope reactor-based control
}
Copy the code

The tree – shaking and Babel

  • Many sources say that tree-shaking will fail if we use Babel-Loader.
  • The premise for Tree-shaking is that modules must be ESModule standard. Code packaged with WebPack must use ESM standards. Before packaging, WebPack assigns modules to different loaders for processing, and packages the results of the loader processing together. When babel-Loader processes JS, it may process esModule conversion to commonJS specification. However, after our experiments, even after using Babel-Loader, tree shaking is still carried out, because the new version of Babel-Loader has automatically turned off esModule conversion for us.
loader: 'babel-loader'.options: {
  presets: [['@babel/preset-env', { modules: 'commonjs' }] // Turn on the esModule conversion to CommonJS, which will not be converted to CommonJS.]}Copy the code
  • Still need to explore

sideEffects

Side effects

  • Allowing us to configure to identify if our code has side effects gives tree-Shaking more space to compress.

  • Side effect: What the module does when it executes besides exporting members. For example, adding the prototype method to the XXX prototype will contaminate the XXX prototype when others introduce it.

  • Generally used to flag NPM packages for side effects

  • How to Use:

    • Use sideEffects to turn this on in webpack.config.js
    • Configure sideEffects: false in packjson to indicate that the code in this project does not have any sideEffects.
  • Make sure your code has no side effects before you use it. Otherwise side effect code will be deleted by mistake.

Webpack code subcontracting/cutting

  • The bundle size is too large and needs to be resolved. Not every module is necessary at startup time.
  • Subcontract and load on demand
    • Multiple entry packing
    • Dynamic import and load on demand

Multiple entry packing

  • Generally suitable for multi-page applications
  • Each page corresponds to a package entry
  • The common parts are extracted separately
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  mode: 'none'.entry: {
    index: './src/index.js'.album: './src/album.js'
  },
  output: {
    filename: '[name].bundle.js'
  },
  optimization: {
    splitChunks: {
      // Automatically extract all common modules into a separate bundle
      chunks: 'all'}},module: {
    rules: [{test: /\.css$/,
        use: [
          'style-loader'.'css-loader']]}},plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: 'Multi Entry'.template: './src/index.html'.filename: 'index.html'.chunks: ['index']}),new HtmlWebpackPlugin({
      title: 'Multi Entry'.template: './src/album.html'.filename: 'album.html'.chunks: ['album']]}})Copy the code

Dynamic import

  • All dynamically imported modules are automatically subcontracted

  • The logic of the code controls when a dynamic import is required, or when the module is loaded.

  • Magic comments that rename dynamically packaged files and allow flexible combinations of files.

miniCssExtractPlugin

CSS sizes > 150KB are best extracted, otherwise embedded in HTML.

Webpack internally provides only js file compression, and for CSS file compression, WebPack recommends optimism-csS-assets – Webpack-plugin.

Webpack recommends that the plug-in for the compressed class be configured uniformly in the Optimization Minize for unified management.

Output file name hash

  • In a production environment, filenames are hashed. To the client, a new file name is a new request, so there is no caching problem.
  • hash
    • At the project level, any change in any part of the project will change the hash value,
  • chunkhash
    • At the chunk level, the hash value of the files along the same path is the same. However, if the files along the same path change, the hash value of the files along the same path changes.
    • For example, A.JS introduces A.SS. A.js and A.SS are on the same road.
  • contenthash
    • File level hash, which changes when the file is modified based on the hash generated by the file.

rollup

Rollup is smaller than WebPack

It’s just an ESModule packager with no additional features

Rollup does not support advanced features like HMR

Purpose: To provide an efficient wrapper that takes full advantage of the ESModule features and builds superior class libraries.

  • The packaged result is surprisingly clean, without the underlying code in WebPack. The result of the packaging is the result after tree-shaking.
  • Plug-ins are the only way rollup extends.
  • The js file packaged by rollup does not automatically find modules under node_modules directly by the NPM module name. Instead, you need to use a plugin: rollup-plugin-node-resolve. So import _ from ‘loads-es’ can go directly to node_module to find the module.
  • By default, Rollup does not support CommonJS specification modules. You can use the rollup-plugin-commonjs plug-in. Modules of the CommonJS specification are now available.
  • Rollup Multi-entry packaging. Code splitting is automatically performed. Code splitting cannot be packaged in IIFE mode. Use AMD in browser environment.

Rollup vs. WebPack

Advantages:

  • The output is flatter
  • Automatically removes unreferenced code
  • The packaging results are still fully readable

Disadvantages:

  • Loading non-ESM third-party modules is complicated
  • Modules end up being packaged into a function, and HRM is not possible
  • In the browser environment, the code splitting function depends on the AMD library.

parcel

  • Parcel is completely zero-configured and has no intrusion into the project. The automatic installation experience allows us to focus more on coding, internal use of multi-process packaging, build faster.
  • But WebPack is more ecological, and WebPack is getting better. Parcel for developers, we get to know them in order to stay sensitive to the technology and better understand where the technology is going.