Webpack static model quick packaging tool

webpack.docschina.org/

Webpack is a static module packaging tool for modern JavaScript applications.

When WebPack works on an application, it internally builds a dependency graph (dependency [/dɪ ɪ pendənsi/] graph [/ SMR æf/]) that maps every module needed for the project and generates one or more bundles! Webpack itself is based on Node.js!

Webpack is a tool for engineering and automating projects in the big front-end era.

There are also several packaging tools: Grunt, gulp, fis, Webpack, Snowpack, vite…

Why use Webpack

  • Code conversion: TypeScript compiles to JavaScript, LESS/SCSS compiles to CSS, ES6/7 compiles to ES5, virtual DOM compiles to real DOM…
  • File optimization: compression JS, CSS, HTML code, compression merged pictures, pictures BASE64 and so on
  • Code segmentation: extract the common code of multiple pages, extract the code that does not need to execute part of the first screen, etc
  • Module merge: In a modularized project, there will be many modules and files, and you need to build functionality to merge modules into a single file
  • Auto refresh: Listen for changes to the local source code, and automatically rebuild and refresh the browser
  • Code validation: Eslint code specification validation and detection, unit testing, etc
  • Automatic publishing: Automatically build the code to publish online and transfer it to the publishing system

CommonJs specification & ES6Module specification

Modularity becomes evolutionary history

  • Singleton design pattern
  • AMD [require.js]
  • CommonJs
  • CMD [sea.js]
  • ES6Module

1) Singleton design pattern

Features: As an early modular programming scheme, singleton design mode can realize module differentiation and avoid global variable pollution; But with the development of the front end, we have to split more and more modules, and the dependencies between modules are more and more complex, singleton mode in dealing with module dependencies, easy to make people “crazy”!

  • Importing JS files into HTML requires importing them in order of dependencies

let xxxModule = (function () { let time = new Date(); const query = function query() { // ... }; const handle = function handle() { // ... }; // window.query = query; // window.query = query; return { query, handle }; }) ();Copy the code

2) AMD module “require.js

Require. js is a modular idea from AMD: import on demand, dependency management

  • One problem with AMD thinking: all dependent modules need to be pre-imported
  • Benefits: Each module is managed
  • [‘ module path ‘]
  • Rely on the moduleRequire ([' dependent module A','B'... ,function(A,B,...) {})
  • Definition moduledefine(function(){ })
  • Define add-dependency modulesDefine ([' dependency module A','B'... ,function(A,B,...) {})

//main.js require.config({baseUrl: 'js/lib',}); require(['moduleB', 'moduleA'], function (moduleB, moduleA) { console.log(moduleB.average(10, 20, 30, 40, 50)); }); //moduleA.js define(function () { return { sum(... args) { let len = args.length, firstItem = args[0]; if (len === 0) return 0; if (len === 1) return firstItem; return args.reduce((total, item) => { return total + item; }); }}; }); // moduleb. js define(['moduleA'], function (moudleA) {return {// args) { let len = args.length, firstItem = args[0]; if (len === 0) return 0; if (len === 1) return firstItem; args.sort((a, b) => a - b); args.pop(); args.shift(); return (moudleA.sum(... args) / args.length).toFixed(2); }}; });Copy the code

3) CommonJS module [we can still use it now]

Advantages: With guide with use

CommonJS module specification

  • Export module exports
  • Import require(‘./ module address ‘)

module.exports = {};

  • Let obj = require(‘./ module address ‘);
  • Let {sum} = require(‘./ module address ‘); [Direct deconstruction assignment]

module.exports = xxx;

  • Let XXX = require(‘./ module address ‘);

If you want to import a built-in Node module (or an installed third-party module), write the module name directly.

Features: Runs only in the Node environment, not in the browser

Taobao “yu Bo” previously developed a plug-in sea-.js, which aims to run the CommonJS template specification on the browser side. He called this module idea “CMD”.

Sea.js is no longer used, but when we use WebPack, webPack supports the commonJS specification, so we can write code directly using the commonJS specification, and finally webPack helps us compile the code that the browser can recognize!

/* ---A.js--- */ const sum = function sum(... params) { return params.reduce((result, item) => { return result + item; }); }; Exports = {sum}; // exports = {sum}; /* -- b.js -- */ let name = 'ha ha '; let A = require('./A'); const average = function average(... params) { return (A.sum(... params) / params.length).toFixed(2); }; module.exports = { average }; /* ---main.js--- */ let A = require('./A'); console.log(A.sum(10, 20, 30, 40)); let B = require('./B'); console.log(B.average(10, 20, 30, 40));Copy the code

4) ES6Module module

Export or export default export, import import

Import import must be written at the beginning of the module

Type =”module” open the ES6Module specification directly in the browser;

1. Export: export

Export const n = 100;

Export const m = 200;

1. Import: import

import * as A from ‘./A.js’

When used: A.n, a.m.

2. Export [export default can only be used once]

Export Default Object/function

export default { sum,func }

2. The import

import A from ‘./A.js’

Export default function sum(){}

Import import sum from./ a.js’

Export default can be used only once in a module

  • Export {XXX: XXX};

Webpack supports both CommonJS and ES6Module, and can mix the two.

Const sum = function sum(const sum = function sum(... params) { let len = params.length; if (len === 0) return 0; if (len === 1) return params[0]; return params.reduce((result, item) => { return result + item; }); }; //export default sum; export default{ sum }; B.JS import A from './A.js'; // ES6Module,'.js' can not be ignored [webpack uses negligible suffix] const average = function average(... params) { let total = A.sum(... params); return (total / params.length).toFixed(2); }; export default average; Import A from './ a.js '; import average from './B.js'; The console. The log (A.s um (12,23,34,45)); The console. The log (business,23,34,45) (12); index.html <! [Live Server] --> <script type="module" src="main.js"></script>Copy the code
  • Support export to export multiple “import methods”
c.js export let n = 100; export let m = 200; export const fn = function fn() { }; Import * as C from './ c. js'; console.log(C); /* import { n, m, fn } from './c.js'; console.log(n, m, fn); * /Copy the code

  • The export default function is supported
D.js export default function () { console.log('fn'); }; // Support the export default function import fn from './ d.js '; console.log(fn);Copy the code
  • Export Default objects are supported
E.js const fn = function fn() { }; const sum = function sum() { }; export default { fn, sum }; // Support the export default object import E from './ e.js '; // const {sum,fn}=E console.log(E); // const {sum,fn}=E console.log(E);Copy the code

/* ---index.html--- */ <! <script type="module" SRC ="main.js"></script> /* The ES6Module specification must be previewed based on HTTP/HTTPS protocols - main. Js - * / / * import, must be written in the module of the first * / import from A '. / a. s'; import average from './B.js'; console.log(A.sum(10, 20, 30, 40)); console.log(average(10, 20, 30, 40)); /* ---A.js--- */ const sum = function sum(... params) { return params.reduce((result, item) => { return result + item; }); }; // export const AA = 'xx'; // export const BB = 'xx'; // export default sum; export default { sum }; /* ---B.js--- */ import A from './A.js'; const average = function average(... params) { return (A.sum(... params) / params.length).toFixed(2); }; export default average;Copy the code

2. The operation phase of NPM

  • Install the difference between global and local
  • How to use commands locally
  • NPX “NPM > 5.2”

3. Operation basis of Webpack

1) installation

If you want to use Webpack, you must install webpack webpack- CLI

  • 1. Install NPM I webpack webpack-CLI -g
    • Uninstall: NPM uninstall webpack webpack -CLI -g
    • Can use the command webpack directly
    • All projects use the same version of WebPack; But if you want to use different versions of Webpack, it is not easy to implement.
  • NPM I webpack webpack-cli –save-dev
    • Or yarn add webpack webpack-cli -d
      • Before using YARN, run yarn init -y to generate package.json
    • You cannot use the webpack command directly
    • Each project has its own version, which does not lead to version conflicts

— — — — — — — — — — — — — — — — — — — — — — how to implement: installation in local project, but also can use the command package?

  • 1. If NPM > 5.2, run $NPX webpack
  • 2. Configure executable script commands in package.json
"Scripts ": {// Script name: the command to execute [premise: webpack is required in the node_modules directory. Bin folder] "build":"webpack"}Copy the code
  • NPM run build NPM run build

2) Zero configuration use

By default, NPM run build looks for index.js files in the SRC folder in the root directory. The default packaged directory is main.js in the dist directory

DIST/ main. JS * Webpack supports CommonJS and ES6 Module specifications by default. This is the dependency package */ $NPX webpackCopy the code

3) Customize basic configurations

webpack.config.js || webpackfile.js

const path = require('path'); Module. exports = {// set package mode development: production: exports [default] // Exports: exports // set package mode development: production: exports [default] // Exports: exports // set package mode development: production: exports 'development', // package entry file directory entry: './ SRC /main.js', // package output directory output: {// output filename filename: 'bundle.js', // output path [must be an absolute path] path: path.resolve(__dirname,'dist')}};Copy the code

  • Development development mode [default uncompressed]

  • Production Production mode [default compression]

4) Customize the configuration file name

Run the webpack command

  • If you don’t write webpack.config.js, by default, you’ll find SRC /index.js and package it to dist/main.js
  • If you’ve written webpack.config.js, follow the rules you’ve written
  • In real projects, it is often the case that we have to distinguish between the environment [development and production] and the two environments go in different configurations

Specifies the rule file to look for when Webpack is packaged

  • @1 creates different rule files
    • Webpack. Config. Development. Js “development environment packaging rules”
    • Webpack. Config. Production. Js “production packaging rules”
  • @2 Configure different script commands to execute a command and make it follow its own rules
scripts": {
    "serve": "webpack --config webpack.config.development.js",
    "build": "webpack --config webpack.config.production.js"
  }
Copy the code
  • $NPX webpack – config webpack. Config. Development. Js
  • Executable script commands can be configured in package.json (development environment specific)

webpack.config.js

const path = require('path'); Module. exports = {// set package mode development: production: exports [default] // Exports: exports // set package mode development: production: exports [default] // Exports: exports // set package mode development: production: exports 'production', // Package entry file directory entry: './ SRC /main.js', // package output directory output: {// output file filename: 'bundle.js', // output path [must be an absolute path] path: path.resolve(__dirname,'dist')}};Copy the code

Webpack. Config. Development. Js development environment

/ / const path = require('path'); module.exports = { mode: 'development', entry: './src/main.js', output: { filename: 'bundle.js', path: path.resolve(__dirname,'dist') } };Copy the code

Webpack. Config. Production. Js production environment

/ / const path = require('path'); module.exports = { mode: 'production', entry: './src/main.js', output: {// [hash]: generates a different hash value for each package based on the content of the file to ensure that the file code is updated. The generated filename is different filename: 'bundle.[hash].min.js', path: path.resolve(__dirname,'dist') } };Copy the code

5) Use plug-ins to package HtmlWebpackPlugin

  • Create a new index.html file in the SRC folder and go to webpack.config.js to write the configuration
  • $NPM I html-webpack-plugin – — save-dev
let HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { ... [new HtmlWebpackPlugin({//=> specify your own template: './ SRC /index.html', //=> output filename: 'index.html', //=> To HASH the imported file (clear the cache), you can also set filename: 'bundle.[HASH].js' in output to generate a different file HASH: True, / / = > control whether and in what way to minimize the output / / = > https://github.com/kangax/html-minifier minify: {collapseWhitespace: true, removeComments: true, removeAttributeQuotes: true, removeEmptyAttributes: true } }) ] }Copy the code

6) Clean the packaging tool CleanWebpackPlugin

  • Each time a tool is packaged, it is necessary to clear the previously packaged content
  • $NPM I clean-webpack-plugin — save-dev
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports={
    plugins:[
        new CleanWebpackPlugin()
    ]
};
Copy the code

7) Configure webpack-dev-server

  • $ NPM install webpack dev - server - save - dev
  • Dev-server configuration: Create a local service that previews compiled content in real time [required for development environment]
  • npm run serve: Automatically open the browser, monitor the code update status in real time, when the code changes, the page will automatically refresh
  1. $NPM Run Serve -> Webpack Server
  • Package and compile according to the rules [put compiled files in memory {temporary place}, not in dist directory]
  • The webpack-dev-server plugin helps us to start a Web service (as devServer has configured it), and what the service accesses is to look it up in memory
  • When the code changes, the started service automatically listens for the code changes, recompiles, and notifies the browser to update automatically
  1. $NPM run build -> ‘webpack’
  • Package and compile according to the rules, and export the compiled files to the dist directory
  • In real development, we would deploy the packaged dist to the server

/* webpack.config.js */ /=> configure dev-server devServer: {//=> port: 3000, host: '127.0.0.1', //=> enable GZIP compression :true, //=> display compilation progress: true, //=> Specify access to resource directory contentBase: Path. resolve(__dirname, "dist"), //=> automatically open browser open: True, / / = > open hot update hot: true, / / = > request broker proxy: {"/" : {target: "http://localhost:8888", secure: ChangeOrigin: true // Change the host value in the request header to server address}}} /* package.json */ "scripts": { "serve": "webpack server", "build": "webpack" }Copy the code

4. Webpack loader: handles style

$ npm i css-loader style-loader less less-loader autoprefixer postcss-loader –save-dev

  • Less Sass Stylus Front-end style precompiled language
    • Less less-loader Compiles less code and processes it into CSS code
    • sass sass-loader
    • Css-loader Parsing CSS @import URL… Code to import external resources
    • Style-loader inserts CSS styles into head
    • Less less-loader Compiles less code
    • Autoprefixer postCSS-loader automatically prefixes [-webkit-, -moz-, -ms-, -o-] according to browser compatibility problems
      • -webkit-transition:.5s;
      • -ms-transition:.5s;
      • -moz-transition:.5s;
      • -o-transition:.5s;
      • transition:.5s;
Module. exports = {//=> config module LOADER module: {//=> Module rules: use the LOADER (default from right to left, from bottom to top) rules: [{test: / \. (CSS | less) $/, / / = > based on regular matching which modules need to handle the use: ["style-loader", //=> insert CSS into HEAD "css-loader", //=> compile @import/URL() this syntax "postcss-loader", //=> set prefix {loader: "Less - loader", the options: {/ / = > loader additional configuration}}}}}]]Copy the code

postcss.config.js

module.exports = {
    plugins: [
require('autoprefixer')
    ]
};
Copy the code

package.json

// https://github.com/browserslist/browserslist
"browserslist": [
"> 1%",
"last 2 versions"
]
Copy the code

1) Mini-CSS-extract-plugin Extracts CSS content

www.npmjs.com/package/min…

  • $ npm i mini-css-extract-plugin –save-dev
  • Mini-css-extract-plugin Extracts CSS content
const MiniCssExtractPlugin=require('mini-css-extract-plugin'); Module.exports = {plugins: new MiniCssExtractPlugin({//=> set filename: 'main.[hash].css' }) ], module: { rules: [{ test: /\.(css|less)$/, use: [/ / "style - loader", / / = > MiniCssExtractPlugin loader in the plug-in is used instead of style way. The loader, "CSS - loader", "postcss - loader", "less-loader" ] }] } }Copy the code

5. Set optimization items to compress CSS/JS

$NPM I optimize- CSS-assets -webpack-plugin uglifyjs-webpack-plugin terser-webpack-plugin — save-dev

const UglifyjsWebpackPlugin=require('uglifyjs-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin'); const OptimizeCssAssetsWebpackPlugin= require('optimize-css-assets-webpack-plugin'); Module. exports = {//=> Set optimization: {//=> set optimization: {//=> Set minimizer: [/ / CSS = > compression (compression way but must specify the JS) new OptimizeCssAssetsWebpackPlugin (), / / JS / / = > compression new UglifyjsWebpackPlugin ({/ / cache: //parallel: true, //parallel: true, //parallel: true, //=> Parallel: true, //sourceMap: true, //=> Start source mapping (easy debugging) //}), new TerserPlugin()]}};Copy the code

6. Image processing in webpack

$NPM I file-loader url-loader html-withimg-loader -save-dev

Module. Exports = {module: {/ / = > module rules: use the loader (default) from right to left rules: [{test: / \ | GIF (PNG | jpe? G) $/ I, use: [{//=> BASE64 //=> file loader: 'url-loader', options: {limit: 200 * 1024, outputPath:'/images', // Output images //name:'[name].[ext]' in dist }}], include: path.resolve(__dirname, 'SRC '), // exclude: // node_modules/ / exclude that directory must not compile}, {// font icon, no way to base64, But you can use the file - loader processing test: / \. (SVG | eot | the vera.ttf | woff | woff2) $/ I use: file - "loader"}, {/ / HTML also processed the image in the test: /\.html$/, use: ['html-withimg-loader'] }] } }Copy the code

7. ES6 conversion based on Babel

babeljs.io/

NPM I babel-loader @babel/core @babel/preset-env core this is which @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/plugin-transform-runtime — save-dev NPM I @babel/runtime @babel/polyfill Needs to download the production environment

  • Babel-loader @babel/core @babel/preset-env core these three
  • {test: /.js$/, use: [{loader: ‘babel-loader’,// { presets:[“@babel/preset-env”] } }] }
    • Options: {presets:[“@babel/preset-env”]} Use this syntax package to upgrade ES6 to ES5
    • However, only some syntactic operations can be converted, and many ES6 built-in apis cannot be converted
      • NPM i@babel/Runtime@babel /polyfill needs to be downloaded in the production environment
      • Import from main.js with import ‘@babel/polyfill’
      • The Promise that ES6 cannot transform, it mainly writes a native Promise itself. And then we’re going to use it as written by the person who used it
      • In addition to the @babel/preset-env syntax package, the built-in API needs to be converted if IE10 and 11 are compatible in the project
      • To implement the built-in API compatibility, we need to import @babel/ Polyfill into the application. “This package implements the built-in ES6 API itself.”
module.exports = { module: { rules: [{ test: /\.js$/, use: [{ loader: 'babel-loader', options: {//=> preset (ES6->ES5) presets: ["@babel/preset-env"], //=> presets: ["@babel/preset-env"], // [ ["@babel/plugin-proposal-decorators", { "legacy": true }], ["@babel/plugin-proposal-class-properties", { "loose": True}], "@babel/plugin-transform-runtime"]}}], //=> set files ignored during compilation and specify directory include: path.resolve(__dirname, 'src'), exclude: /node_modules/ }] } }Copy the code

8. Multiple entrances & Multiple exits

const htmlPlugins = ['index', 'login'].map(chunk => {
    return new HtmlWebpackPlugin({
        template: `./${chunk}.html`,
        filename: `${chunk}.html`,
        hash: true,
        chunks:[chunk,'jquery'],
        minify: {
            collapseWhitespace: true,
            removeComments: true,
            removeAttributeQuotes: true,
            removeEmptyAttributes: true
        }
    });
});
module.exports={
    entry: {
        index: "./src/index.js",
        login: "./src/login.js",
        jquery:"./src/jquery.js"
    },
    output: {
        filename: "[name].[hash].js",
        path: path.resolve(__dirname, "dist")
    },
    plugins:[
        ...htmlPlugins
    ]
};
Copy the code

Scaffolding vue/cli

  • 1. Scaffolding: vue->@vue/cli react->create-react-app
  • 2. Creating projects based on scaffolding will help us set up all webPack configuration items by default
  • 3. Vue vue- CLI old version @vue/ CLI new version
  • 4. NPM i@vue /cli -g Install vue/ CLI globally
  • 5. Vue create XXX name “Chinese characters, special symbols and uppercase letters cannot appear”

  • 1.@vue/ CLI is the scaffolding for the VUE framework.
  • 2. Default processing:
    • The VUE module is installed
    • Complete the general configuration of WebPack [mode, entry, exit, loader, plug-in, optimizer…]
    • Support for ESLint syntax checking: Code written that does not conform to syntax specifications will report errors when compiled
  • 3. The webpack configuration file is stored in node_modules by default
    • NPM run serve Run vue-cli-service serve
      • Compile the package code [in memory]
      • Start a Web service based on webpack-dev-server to run the compiled content
      • Support hot update, code modification, timely compilation, real-time refresh browser preview
    • NPM run build Run vue-cli-service build
      • Compile package code
      • Put it in the dist directory
  • 4. How do I modify the default configuration items?
    • The root directory creates vue.config.js
      • The publicPath prefix is the root directory or the current directory/Yes The root directory
      • OutputDir is packaged under that file
      • LintOnSave: false esLint whether to enable
      • productionSourceMap
        • Add map in order to report error can know where error, but package compilation will be slow and inconvenient debugging
  • 5. Handle browser compatibility
    • Package. json according to compatible browser: set CSS prefix & implement JS syntax conversion
    • polyfills
// package.json
"browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
Copy the code

Package of vue. Json

File directory

  • Node_modules Specifies the installed module
  • Public page template, multiple page development to write multiple templates
    • Favicon. ico header icon
    • Index.html template for the home page
      • <%= BASE_URL %> refers to the public directory, which is compiled by Webpack
      • % > < % = htmlWebpackPlugin. Options. The title of the page title can webpack specified in the configuration items
    • .

  • Why can’t the specified template of EL use HTML /body?
    • Because you can new Vue multiple times but there’s only one HTML /body.
  • In the index.html template page, we might import some resources or write some code ourselves that we don’t want to end up bundled together with styles and code from other components. “It’s too big to pack together, so we want to preload and render all this code we’ve written, or we want to write it inline to reduce the white screen.”
  • Such as:
    • The dynamic calculation of rem and PX conversion ratio of the code written here, priority loading
    • Because the packed file is large, it takes some time to load, and the Loading process will appear a blank screen. In this case, we can write some code for Loading or skeleton screen. “Client Loading” provides users with humanized experience and “reduces blank screen time”
    • .
  • Because webPack is based on ES6Module or CommonJs specification implementation import/export and packaging, if our JS does not support these two specifications, so it cannot be used in WebPack, can only be based on

Write for the first time, if have what inadequacy or have the wrong place, hope everybody more mention point! Thank you (* ̄)  ̄)