webpack

webpack

webpack

webpack webpack

Css

import './style.css' import React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render(<div>hello</div>,document.getElementById('root'));
body{ background: red } .class1{ background: red }

.class1
src

purgecss css glob glob-all mini-css-extract-plugin paths npm i -D purgecss-webpack-plugin mini-css-extract-plugin glob webpack.config.js + const glob = require('glob'); + const PurgecssPlugin = require('purgecss-webpack-plugin'); { test:/\.css/, include: path.resolve(__dirname,'src'), exclude:/node_modules/, use: [{ loader: MiniCssExtractPlugin.loader },'css-loader'] } module.exports = { mode: 'development', plugins: [ new PurgecssPlugin({ paths: glob.sync(`${path.join(__dirname, "src")}/**/*`, { nodir: true }) // }), new MiniCssExtractPlugin({ filename: '[name].css', chunkFilename:'[id].css' }) ] }

npm install image-webpack-loader --save-dev

file-loader

loader: "image-webpack-loader", options: { mozjpeg: { progressive: true, quality: 65 }, //optipng.enabled: false will disable optipng optipng: { enabled: false, }, pngquant: { quality: [0.90, 0.95], speed: 4 }, gifsicle: { interlaced: false, }, //the webp option will enable WEBP webp: { quality: 75 } }

Tree-shaking && Scope-Hoisting

Tree-shaking

,

main.js

import { minus } from "./calc"; console.log(minus(1,1));

calc.js

import {test} from './test'; export const sum = (a, b) => { return a + b + 'sum'; }; export const minus = (a, b) => { return a - b + 'minus'; };

test.js

export const test = ()=>{ console.log('hello') } console.log(test());

minus
,
test.js
!

mode:production
tree-shaking
,
'hello'
,

package.json

"sideEffects":false,

css
css
import './style.css'

,

tree-shaking
es6 ,
require
css, ,
css

"sideEffects":[ "**/*.css" ]

tree-shaking
,

optimization:{ usedExports:true }

4.2 Scope Hoisting

,

let a = 1; let b = 2; let c = 3; let d = a+b+c export default d; // d import d from './d'; console.log(d)

console.log(6)

5.DllPlugin && DllReferencePlugin

import React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render(<h1>hello</h1>,document.getElementById('root'))

DllPlugin

react
react-dom

webpack.dll.js

const path = require('path'); const DllPlugin = require('webpack/lib/DllPlugin'); module.exports = { entry:['react','react-dom'], mode:'production', output:{ filename:'react.dll.js', path:path.resolve(__dirname,'dll'), library:'react' }, plugins:[ new DllPlugin({ name:'react', path:path.resolve(__dirname,'dll/manifest.json') }) ] }

"webpack --config webpack.dll.js
dll
manifest.json
,
react.dll.js

manifest.json
react.dll.js

DllReferencePlugin

const DllReferencePlugin = require('webpack/lib/DllReferencePlugin'); const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin'); // new DllReferencePlugin({ manifest:path.resolve(__dirname,'dll/manifest.json') }), // react.dll.js new AddAssetHtmlWebpackPlugin( { filepath: path.resolve(__dirname,'dll/react.dll.js') } )

DllPlugin

webpack5

let btn = document.createElement('button'); btn.innerHTML = ' '; btn.addEventListener('click',()=>{ import('./video').then(res=>{ console.log(res.default); }); }); document.body.appendChild(btn);

output:{ chunkFilename:'[name].min.js' } import(/* webpackChunkName: "video" */ './video').then(res=>{ console.log(res.default); })

video.min.js

webpack-bundle-analyzer

npm install --save-dev webpack-bundle-analyzer

const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer'); mode !== "development" && new BundleAnalyzerPlugin()

SplitChunks

SplitChunks

entry:{ a:'./src/a.js', b:'./src/b.js' }

a,b

jquery
,
externals

SplitChunks

splitChunks: { chunks: 'async', // minSize: 30000, // maxSize: 0, minChunks: 1, // maxAsyncRequests: 5, // maxInitialRequests: 3, // automaticNameDelimiter: '~', // automaticNameMaxLength: 30, // name: true, cacheGroups: { // vendors: { // test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { minChunks: 2, priority: -20, // reuseExistingChunk: true } } }

async
initial

lodash
,
async

import('lodash')

c.js
,

splitChunks: { chunks: 'all', name: true, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { minSize:1, // minChunks: 2, priority: -20, } } }

chunks

HMR - Hot Module Replacement webpack

devServer:{ hot:true } new webpack.NamedModulesPlugin(),

js

import sum from './sum'; console.log(sum(1,2)); if(module.hot){ // module.hot.accept(); // }

IgnorePlugin

import
require

new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)

const SpeedMeasureWebpackPlugin = require('speed-measure-webpack-plugin'); const smw = new SpeedMeasureWebpackPlugin(); module.exports =smw.wrap({ });

noParse

module.noParse
jq

noParse:/jquery/

resolve

extensions

  • extensions req uire import

alias

  • webpack
  • bootstrap bootstrap, node_modules
resolve: { extensions: [".js",".jsx",".json",".css"], alias:{}, modules:['node_modules'] },

include/exclude

loader
,
loader
,
loader

{ test: /\.js$/, use: "babel-loader", //include:path.resolve(__dirname,'src'), exclude:/node_modules/ },

happypack

npm install --save-dev happypack

const HappyPack = require('happypack'); rules:[ { test: /\.js$/, use: 'happypack/loader?id=jsx' }, { test: /\.less$/, use: 'happypack/loader?id=styles' }, ] new HappyPack({ id: 'jsx', threads: 4, loaders: [ 'babel-loader' ] }), new HappyPack({ id: 'styles', threads: 2, loaders: [ 'style-loader', 'css-loader', 'less-loader' ] })

preload , prefetch

preload( )

  • preload js css
  • preload ,
  • ,
    • Highest
    • High
    • Medium
    • Low
    • Lowest
  • //Low

<link rel="preload" as="script" href="utils.js"> import( `./utils.js` /* webpackPreload: true */ /* webpackChunkName: "utils" */ )

prefetch( )

  • prefetch preload
<link rel="prefetch" href="utils.js" as="script"> button.addEventListener('click', () => { import( `./utils.js` /* webpackPrefetch: true */ /* webpackChunkName: "utils" */ ).then(result => { result.default.log('hello'); }) });

preload vs prefetch

  • preload
  • prefetch
  • preload, prefetch

  • webpack
    • babel-loader
    • cache-loader
    • hard-source-webpack-plugin

babel-loader

  • Babel js babel-loader

{ test:/\.js$/, exclude:/node_modules/, use: [{ loader: "babel-loader", options: { cacheDirectory: true } }] },

cache-loader

  • loader loader,
  • , loader loader

cnpm i cache-loader -D

const loaders = ['babel-loader']; module.exports = { module: { rules: [ { test:/\.js$/, use: [ 'cache-loader', ...loaders ], include: path.resolve('src') } ] } }

cnpm i friendly-errors-webpack-plugin node-notifier -D

2.1.2 webpack.config.js const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin'); const notifier = require('node-notifier'); const ICON = path.join(__dirname, 'icon.jpg'); module.exports = { mode: "development", devtool: 'source-map', context: process.cwd(), entry: { main: "./src/index.js", }, output: { path: path.resolve(__dirname, "dist"), filename: "main.js" }, plugins:[ new HtmlWebpackPlugin(), new FriendlyErrorsWebpackPlugin({ onErrors: (severity, errors) => { const error = errors[0]; notifier.notify({ title: "Webpack ", message: severity + ': ' + error.name, subtitle: error.file || '', icon: ICON }); } }) ] };

cnpm i speed-measure-webpack5-plugin -D

webpack.config.js

const SpeedMeasureWebpackPlugin = require('speed-measure-webpack5-plugin'); const smw = new SpeedMeasureWebpackPlugin(); module.exports = smw.wrap({ mode: "development", devtool: 'source-map', ... });

cnpm i webpack-bundle-analyzer -D

webpack.config.js
const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer') module.exports={ plugins: [ new BundleAnalyzerPlugin() ] }

webpack.config.js
const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer') module.exports={ plugins: [ new BundleAnalyzerPlugin({ analyzerMode: 'disabled', // http generateStatsFile: true, // stats.json }), ] } "scripts": { "build": "webpack", "start": "webpack serve", "dev":"webpack --progress", "analyzer": "webpack-bundle-analyzer --port 8888 ./dist/stats.json" }