Knowledge of NPM

  1. The version number 1.2.3

    • Major version number: Code refactoring
    • Version number in 2: Code plus features
    • Minor version: Bug fixes
  2. The version prefix ^ ~ * installs the specified version dependency without the prefix symbol

  3. Difference between -d and -s

    • -D: dependencies
    • -S: devDependencies
    • Add dependencies for dependencies only
    NPM install --only=prod NPM install --only=dev NPM install // Full installationCopy the code
  4. NPM install process

    • Look for package version information filespackage-lock.json, follow it to install
    • Look for dependencies in package.json and check for other version information files in the project
      • If package version information does not exist the file is completely followedpackage.jsonTo install and generate a version information file
      • Only install if version information files existpackage.jsonWhich packages are present in the version information that is not
    • If a new package is found, update the version information file
  5. If a package is found to be inconsistent with expectations, it should:

    • Look at the source and version of the package in the version information because it has the highest priority during installation

webpack

Front-end modularization No special configuration can only handle JS (ES5 and below) flexible Loader Plugin pluggable

  1. webpackCan only handle itselfes6The following versions of JS
  2. loaderThe order
  3. pluginuse

scope

Concept: Accessibility of variables, functions, and objects while the code is running

Global scope

When you start writing your javascript code in a file it’s already in global scope and there’s only one global scope in js execution and all of the globally-scoped variables and resources are going to be mounted on the global object and in the browser that global object is window; In Node, the global object is global

A = 1 var b = 2 // window.b = 2 let c = 3 // es6 let block scope window.c = undefinedCopy the code

Local scope

Block scope

modular

Scope encapsulation reusability uncoupling (breaking the system into modules breaking up a large system uncoupling more parts of the system when a part of the system changes module can help us quickly locate the problem module (encapsulating the implementation of the function within itself) as long as the interface exposed by the module does not change Changes in logic within a module do not affect other modules.

A page with multiple functions will put multiple functions of the corresponding JS through the outer chain of the following code: The three js file sharing a global scope In any one file for the top-level scope of a variable or function declarations can be exposed in the global Other script variables may obtain it and don’t want to When the application scale and complexity of rose It is easy to occur between these scripts naming conflicts Which can lead to unpredictable problems

<script src="./moduleA.js"></script>
<script src="./moduleB.js"></script>
<script src="./moduleC.js"></script>
Copy the code
// moduleA.js: var name = 'Lucy' // moduleB.js: var name = 'Jack' // moduleC.js: // moduleC wanted to use the name variable in moduleA, but moduleB overwrites the name variable in moduleA, so the name obtained is wrong console.log(name).Copy the code

Initial solution: Add namespaces

Disadvantages: Still unresolvable variable methods in files can be accessed and modified arbitrarily (solved using closures)

// moduleA.js:
var a = {
  name: 'Lucy',
  tell () {
    console.log('My name is.'.this.name)
  }
}
// moduleB.js:
var b = {
  name: 'Jack',
  tell () {
    console.log('My name is.'.this.name)
  }
}
// moduleC.js:
console.log(a.name)
a.name = 'Beta'
Copy the code

Early modular writing

// moduleA.js:
var moduleA = (function() {
  var name = 'Lucy'
  return {
    // name,
    tell () {
      console.log(name)
    }
  }
})()

// Further rewrite the immediate function for the standard module implementation
(function(window) {
  var name = 'Lucy'
  function tell() {
    console.log(name)
  }
  window.moduleA = { tell }
})(window)
Copy the code

Evolution of modularity

The modular approach has come a long way since the immediate implementation of the function implementation method. There are three important stages: AMD COMMONJS ES6-Module

AMD

The AMD specification is not widely used today and uses a defined Module that accepts three parameters:

  • The id of the current module (give the module a name)
  • Dependencies of the current module
  • It can be a function/object
    • If it is a function, export the return value of the function as the interface to define the module
    • If it is an object, the object is the exported value of the current module

Benefits:

  • The display shows what other modules each module depends on
  • The fact that a module’s definition is not bound to a global object increases the security of the module without fear of tampering elsewhere
define('getSum'['math'].function(math) {
  return function(a, b) {
    console.log('sum:', math.sum(a + b))
  }
})
Copy the code

COMMONJS

Originally proposed in 2019 to define module standards on the server side rather than for browser environments, nodeJs has adopted and implemented parts of its specification, making the following adjustments to the module system. In general, there is no strict distinction between COMMONJS and nodeJs module standards (what is the difference between the two standards)

In CommonJS each file is a module and has its own scope and context

// Module dependencies are introduced via the require function
const math = require('./math')
// Exports through exports
exports.getSum = function(a, b) {
  return a + b
}
Copy the code

Amd and commonJs share the same feature: the dependency of modules must be displayed for import. This makes it easier to maintain complex modules without worrying about the order of import between modules

ES6 Module Indicates the recommended modular setting

/ / the import import
import math from './math'
/ / export export
export function sum(a, b) {
  return a + b
}
Copy the code

Webpack packaging

  • webpackwithExecute function immediatelyThe relationship between
  • The core logic of packaging
// Install dependencies /* package */ NPM webpack -g NPM webpack-cli -g /* Monitor project directory file changes */ NPM webpack-dev-serve -g // Monitor project directory file changes when the source file changes will be dynamic and real-time repackage And automatically refresh the browserCopy the code
  1. Webpack presets some configuration even when executing the Webpack command without configuration

    D:\study\webpackTest>webpack // Find the current project directory SRC /index.js to start packing exit is <projectDir>/dist/mainCopy the code
  2. When webpack runs, it will look for webpack.config.js and pack it according to the configuration of the file

  3. webpack-dev-server

    // "webpack-cli": "^4.7.2" // webpack-cli version is not compatible with webpack-dev-server ": "^3.3.12",
    D:\study\webpackTest\react-demo>webpack-dev-server
    internal/modules/cjs/loader.js:883
      throw err;
      ^
    
    Error: Cannot find module 'webpack-cli/bin/config-yargs'
    
    Copy the code
  4. Common Loader Loaders are loaded first in the stack and then executed

    // cssloader NPM install css-loader NPM install style-loader /** * Babel [1, 2, 3].map(e => console.log(e)) // use: Babel SRC /test.js NPM I @babel/core @babel/cli -g // convert rules; The core function of this package is to convert the high version of es code to ES5. In the early years of Babel, we used a series of plug-ins, but this is a bit trivial. Babel officially integrates some plug-ins into a package. Babel SRC /test.js --presets=@babel/preset-env // Print out NPM i@babel /preset-env /* Babel support configuration file */Copy the code
  5. Using Babel, Babel supports configuration files:

    • Configure it in package.json
    {
     "babel": {
       "presets": ["@babel/preset-env"]}}Copy the code
    • Configure the highest priority in.babelrc (Babel automatically looks for.babelrc)
  6. Babel is used in Webpack

    • You need to use babel-loader which depends on @babel/ core@babel /cli
      NPM I Babel -loader -d NPM i@babel/core@babel /cli -d // If preset is installed globally, it can not be installed // Specify a rule to change the high version ES code to a low version NPM i@babel /preset-env -d // If the react project escapes the JSX code NPM i@babel /preset-react -dCopy the code
    • Configure in webpack.config.js
      {
        module: {
          rules: [{test: /.jsx? /,
              exclude: /node_modules/.// exclude
              include: [],
              use: {
                loader: "babel-loader" // babel-loader relies on @babel/ core@babel /cli}}]}}Copy the code
  7. Configure HTML – webpack – the plugin

    const htmlWebpackPlugin = require('html-webpack-plugin')
    const path = require('path')
    module.exports = {
    plugins: [
     new htmlWebpackPlugin({
       // template: '/react-demo/ SRC /index.html' // The absolute path of the file to be processed
       template: path.resolve(__dirname, '/react-demo/src/index.html'), // The absolute path of the file to be processed
       filename: 'index.html' // The packaged target file name}})]Copy the code
  8. Webpack-dev-server enables the webpack-dev-server service to listen for changes to the project directory files when the source files are dynamically repackaged in real time (no packaged files are actually generated, which can be interpreted as existing in the cache) and automatically refresh the browser You can configure to automatically update content without refreshing the browser — hot updates

    
    const webpack = require('webpack')
    
    module.exports = {
      devServer: {
        open: true.// Automatically open the browser
        hot: true / / hot update
      },
      plugins: [
        new webpack.HotModuleReplacementPlugin()
      ]
    }
    
    // Hot update error message
    // index.jsx:
    if (module.hot) {
      module.hot.accept(err= > {
        console.log('Hot update BUG:', err)
      })
    }
    Copy the code
    1. Webpack-dev-server has its own default configuration items and can specify configurations
      /** * open specifies whether to automatically open the browser * config specifies the file path. The default is webpack.config.js */ webpack-dev-server --open // automatically open the browser Webpack-dev-server --config // Read the devServer configuration in webpack.config.js // it is possible to split the production and development environment configuration into two files to configure the need to specify the file webpack-dev-server -- config build/webpack. Dev. Conf. Js/read/build/webpack config. Dev. DevServer configuration in jsCopy the code

Webpack performance tuning

  • Optimization of packaging results
  • Optimization of construction process
  • Tree-Shaking

Optimization of packaging results

  1. Webpack compresses the code automatically when packaging the production environment

    webpack --mode production
    Copy the code
  2. Webpack can also be customized packaging tools such as Webpack official provide terser-webpack-plugin

     // Because compression is very important, WebPack has a special optimization property for compression
     const TerserPlugin = require('terser-webpack-plugin')
    
     module.exports = {
       optimization: {
         minimizer: [
           new TerserPlugin({
             // cache: true, // Enable cache attribute removed
             parallel: true.// enable multithreading; Compression is time consuming
             terserOptions: {
               compress: {
                 unused: true.// Automatically eliminate useless code
                 drop_debugger: true./ / remove the debugger
                 drop_console: true / / remove the console}},})]}}/** * there was ugligy. js that was pretty good at compressing ES5 but not so good at compressing ES6 * so there was a ugliy-Es project that handled ES6; The Uglip-ES * tenrser-webpack-plugin is a branch of the Uglip-es project pulled to continue the maintenance since no one has ever maintained it */
    Copy the code
  3. Webpack results analysis optimizes by building large files

    / / installation: npm i webpack-bundle-analyzer -D const BundleAnalyzerPlugin = require('webpack-bundle-plugin').BundleAnalyzerPlugin module.exports = { plugins: [ new BundleAnalyzerPlugin() ] }Copy the code

Optimization of construction process

Build speed and build volume are often coupled when packaging can be

  1. Open the cache
  2. Enabling multi-threadingHappyPack,thread-loader

Nodejs is a single-threaded model, so webPack running on NodeJS is single-threaded, so webPack needs to do one thing at a time. To do multiple things together, a multi-core CPU is required. Simple projects using multi-threaded packaging will waste more CPU resources, which will not only slow down the packaging speed

Multithreaded packaging is implemented in Webpack and it does this from the thread dimension; Happypack,thread-loader, they’re creating thread pools; Because Webpack and Node are single-threaded, the number of processes is necessary to take advantage of multi-threading; But in Webpack, only multithreading is behind the use of multi-process

The happyPack plugin allows you to start a multi-process process by splitting tasks into sub-processes and executing them concurrently. The sub-processes then return the results to the main threadloader: It is optimized for loaders, it will put loaders in a thread pool (worker) to achieve the purpose of multi-threaded building. Use must be placed before all loaders (loader is stack order).

Thread-loader: Which parts of the build process are time-consuming:

  1. parsing

Webpack performs recursive processing on files as they are packaged; Libraries like jquery and Echarts are very large and not modularized. Standard Webpack takes time and makes no sense to parse these files Js module.exports = {noParse: /node_modules/(jquery.js)/}

  1. Looking for:
    • Match file in rules
        module.exports = {
          rules: [{test: /.jsx? /,
              exclude: /node_modules/./ / node_modules ruled out
              include: path.resolve('src'), // Match the specified file (which can be a regular file) include has a higher priority than exclude and test, so include has the highest priority if the three conflict}}]Copy the code

Other ideas:

  • Optimizations can also be built through precompilation
  • You can also do this on the Loaderfast-sass-loaderParallel processing of SASS files is many times faster than sass-Loader
  • SourceMap Time critical Set this parameter to false

Tree-shaking AN implementation of DCE

First, WebPack itself analyzes the introduction of modules in ES6, removes unwanted import imports, and then removes unwanted modules with tools such as tenser-plugin (these tools are only available in mode) Remove useless code for production only import references for development)