- 1、webpack的基础操作
- 2、基于自定义配置项打包编译(环境区分)
- 3、配置HTML页面模版进行打包预览
- 4、配置多入口的打包编译
- 5、 webpack中的加载器loader: 处理样式的
- 6、mini-css-extract-plugin 抽离CSS内容 改内嵌为外链式
- 7、 设置优化压缩CSS/JS
- 8、webpack中处理图片资源、字体图标(优化压缩)
- 9、三种方式引入第三方模块 expose-loader
- 10、基于babel实现ES6的转换和ESLint语法检测
- 11、设置sourceMap
- 12、 watch监控
- 12、 resolve设置 解析第三方包
- 13、 快速开发
- 14、webpack的优化
- 14-4、 happypack 可以实现多线程 来打包 进程
- 14-5、 webpack自带的优化
- 14-6、提取公共代码 splitChunks
- 14-7、懒加载 靠的就是import语法
- 14-8、热更新插件
- 14-9、PWA 离线应用
1、webpack的基础操作
目前@vue/cli和create-react-app基本上采用的是webpack4.0以上版本,4版本需要webpack和webpack-cli
安装
npm init -ynpm i webpack@4.44.2 webpack-cli@3.3.11 -D
零配置使用
webpack默认会把当前项目src目录下的文件进行打包编译(默认index.js),编译到dist文件目录下(webpack编译代码的过程中支持CommonJS规范和ES6Module规范)
|- src
当前源代码
|- dist
编译后的文件
npx webpack或者script中配置webpack
自己定义webpack打包配置
webpack.config.js OR webpackfile.js
编写自定义的webpack配置项,以后webpack打包编译的时候是按照自己配置的内容进行打包编译处理的(文件根目录)
webpack.config.js
const webpack = require('webpack')module.exports = {// 设置编译的入口文件entry:'src/main.js',// 设置编译的出口文件output:{// 编译后的文件, 添加hash保证编译文件的唯一,清除强缓存filename: 'bundle.[hash:8].min.js',path: path.resolve(__dirname,'build')},// 设置开发环境还是生产(默认)mode:'production'}
强缓存协商缓存,缓存到浏览器,再次访问访问的是存储在本地内存的内容
真实项目中为了在文件更新后,清除强缓存的影响,我们在文件中导入的文件,一般都设置随机数或者不同的HASH值
2、基于自定义配置项打包编译(环境区分)
添加类型声明 提供提醒
yarn add -D @types/webpack
/*** @type {import('webpack').Configuration}*/
2-1 、区分环境变量,自定义配置文件名

npx webpack —config webpack —config webpack.config.prod.js
"scripts": {"serve":"webpack --config webpack.config.dev.js","build":"webpack --config webpack.config.prod.js"}
webpack.config.dev.js
// 开发环境const path = require('path')module.exports = {// 设置编译的入口文件entry:'./src/main.js',// 设置编译的出口文件output:{// 编译后的文件filename: 'bundle.js',path: path.resolve(__dirname,'build')},mode:'development'}
webpack.config.prod.js
// 生产环境const path = require('path')module.exports = {// 设置编译的入口文件entry:'./src/main.js',// 设置编译的出口文件output:{// 编译后的文件filename: 'bundle.[hash].min.js',path: path.resolve(__dirname,'build')},}
2-2、 webpack.DefinePlugin 自定义环境变量
module.exports = {plugins:[new webpack.DefinePlugin({DEV: JSON.stringify('production'), // console.logFLAG:'true',EXPORESSION: '1+1'})]}
2-3、webpack-merge 彻底解决生产环境和开发环境的不同配置需求
// webpack.dev.js
let { smart } = require('webpack-merge')let base = require('./webpack.base.js')module.exports = smart(base,{mode: 'development'})
3、配置HTML页面模版进行打包预览
- 到目前问题是每一次代码编译后,都需要手动的去修改html页面中指定的带有hash的js文件,不智能化
这时需要一个插件 html-webpack-plugin
- 是否存在一个插件,可以帮我们创建一个web服务,实现类似live-serve预览的效果
服务可以自动监听代码的改变,自动刷新浏览器看到的最新效果,除了配置项修改了 需要手动执行,其他的都自动化处理 webpack-dev-server
- 每次打包的时候都需要清除掉之前的打包结果,build下只保留最新的打包文件 clean-webpack-plugin
3-1、html-webpack-plugin
npm i html-webpack-plugin —save-dev

后面压缩的文件导入到这个页面模版中
const HtmlWebpackPlugin = require('html-webpack-plugin')plugins:[new HtmlWebpackPlugin({// 模版路径template:"./public/index.html",// 编译后生成的文件名filename:"index.html",// 是否把编译后的资源文件导入页面中都设置HASH(清缓存,和output中设置HASH值是一样的, 和output设置HASH是一样的效果,只要设置一个地方即可)hash:true,// 把模版中的HTML代码也进行压缩编译配置 https://github.com/kangax/html-minifierminify:{collapseWhitespace:true, // 去除空格removeComments:true, // 去掉注释removeAttributeQuotes:true, // 去除属性的双引号removeEmptyAttributes:true, // 去除空属性removeEmptyElements:true // 去除空的元素}})]
在模版中可以自己单独导入一些CSS/JS/图片等资源文件
1、自己导入的文件不受webpack编译的影响(不会和其他模块的文件编译在一起), 所有有时候会单独导入一些公共的资源文件
2、有些资源不支持CommonJS和ESModule规范,只能自己手动导入
3-2、clean-webpack-plugin
npm i webpack-dev-server —save-dev
const { CleanWebpackPlugin }= require('clean-webpack-plugin')plugins:[// 每次打包都把之前的清空new CleanWebpackPlugin('./dist') // 排除 cleanOnceBeforeBuildPatterns: ['!markdown/**/*']]
3-3、copy-webpack-plugin 将不参与打包的文件进行拷贝到dist目录下
const CopyWebpackPlugin = require('copy-webpack-plugin')plugins:[new CopyWebpackPlugin([{from:'doc', to:'./'}])]
3-4、webpack-dev-server
解决跨域 1、代理 2、before函数内mock 3、node里启动
https://webpack.js.org/configuration/dev-server/ npm i webpack-dev-server —save-dev
编译好的结果放在了内存中,不会像webpack一样把编译后的东西放在build下,dev-server仅仅是在开发模式下,随时编译并且预览的,项目部署的时候,还是需要webpack build
// 配置DEV-SERVER 内存中编译打包devServer: {before(app){ // 调用内部服务 mock数据app.get('/user',(req,res)=>{res.json({name:'rockshang - before'})})},// 端口port: 3000,// 开启GZIP压缩compress: true,// 显示编译进度progress:true,// 指定访问资源目录contentBase: path.resolve(__dirname,'dist'),// 自动打开浏览器open:true,// 开启热更新hot:true,// 请求代理proxy:{"/api": {target:"http://localhost:3000",pathRewrite: { '/api':'' }, // 重写api 代理到express服务器// secure: false, // true 为https , false 为http// changeOrigin: true // 把请求头当中的host值改为服务器地址}}}
启动webpack-dev-server
npx webpack-dev-server
或者脚本中加
"script":{"serve": "webpack-dev-server"}
// xhr 请求let xhr = new XHMLLRequest();xhr.open('GET','/api/user', true) // 8080 => express => 3000xhr.onload = function(){xhr.log(xhr.response);}xhr.send();// node 服务 将webpack在服务端启动const express = require('express');const app = express()const webpack =require('webpack')// 中间件const middle = require('webpack-dev-middlewrare')let config = require('./webpack.config.js')let compiler = webpack(config)app.use(middle(compiler))app.get('/api/user',(req,res)=>{res.json({name:'rock shang'})})app.listen(3000)
3-5、webpack.BannerPlugin 版权插件
let webpack = require('webpack')plugins:[new webpack.BannerPlugin('make 2019 by rock')]
4、配置多入口的打包编译
多页面的开发,需要配置多个页面入口、多个js入口
chunks 指定当前页面的依赖项,如果多页面都依赖某个js,可以独立打包
配置多入口
// entry:'./src/main/js'// 多入口 KEY:VALUEentry: {// 如果不想JQ和其他JS合并在一起,想独立打包可以, 单独引jquery,// 然后在chunks里面配置jquery,使每个页面都引用jquery: 'jquery',index:"./src/main.js",login:"./src/login.js"},output:{ // [name] index.html or login.htmlfilename:'[name].[hash].min.js',path:path.resolve(__dirname,'build')}
配置多页面模版

webpack.config.js
const htmlPlugins = ['index','login'].map(item=>{return new new HtmlWebpackPlugin({template: `./public/${item}.html`,filename: `${item}.html`,chunks:['jquery',item], // 设置多入口时的打包的哪个js进来,不写全部引入minify: {collapseWhitespace: true, // 去除空格removeComments: true, // 去掉注释removeAttributeQuotes: true, // 去除属性的双引号removeEmptyAttributes: true, // 去除空属性removeEmptyElements: true,},}),})module.exports = {// ...plugins:[...htmlPlugins]}
默认打开的是index.html 页面, 登陆页也已经生成了,只需要输入localhost:3000/login.html
5、 webpack中的加载器loader: 处理样式的
处理less npm install css-loader style-loader less less-loader autoprefixer postcss-loader —save-dev 处理scss npm i sass node-sass sass-loader css-loader style-loader autoprefixer postcss-loader —save-dev
module.exports = {// 配置模块加载器LOADER//...moudule: {// 模块规则,使用加载器,从右向左执行,从下向上执行rules:[{test: /\.(css|less)$/i, // 基于正则处理use:["style-loader", // css插入到HEAD中,内嵌式加入"css-loader", // 编译解析@import/URL这种语法"postcess-loader", // 设置前缀,兼容css3写法, 需要搭配autoprefixer一起使用,需要额外配置{loader:"less-loader",options:{// 加载器额外配置}}]}]},//...}
postcss.config.js
module.exports = {plugins:[require('autoprefixer')],}
package.json —— 处理浏览器的兼容列表
// https://github.com/browserslist/browserslist"browserslist":["> 1%", // 兼容百分之99的浏览器"last 2 versions" // 兼容最近两个版本的浏览器],
可以在页面中直接引用但是会发http请求,真实项目中,入口文件中会应用项目所需要的大部分资源
- 样式资源
- JS资源
- 各种模块
在入口处引入,webpack会根基资源文件的依赖关系全部合到一起
import ‘./static/css/index.css’
6、mini-css-extract-plugin 抽离CSS内容 改内嵌为外链式
https://www.npmjs.com/package/mini-css-extract-plugin npm i mini-css-extract-plugin —save-dev
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')module.exports = {//...plugins:[// 使用插件new MiniCssExtractPlugin({falename: '[name].[hash].min.css'})]//...module:{rules:[{//替换 "style-loader",MiniCssExtractPlugin.loader,"css-loader","postcss-loader","less-loader"}]},//...}
7、 设置优化压缩CSS/JS
安装
npm i optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin terser-webpack-plugin -D
webpack.config.js
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');// const TerserPlugin = require('terser-webpack-plugin');const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')module.exports = {// ...// 设置优化项optimization:{// 设置压缩方式minimizer:[//=> 压缩CSS(但是必须指定JS压缩方式)new OptimizeCssAssetsWebpackPlugin(),//=> 压缩JS 下面两个用一个即可new UglifyjsWebpackPlugin({cache:true, // 是否使用缓存parallel:true, // 是否是并发编译sourceMap:true // 启动远吗映射 (方便调试)}),// new TerserPlugin()]},//...}
8、webpack中处理图片资源、字体图标(优化压缩)
npm i file-loader url-loader html-withimg-loader -D
webpack.config.js
module.exports = {//...module: {rules: [//...{test:/\.(png|jpe?g|gif|ico|bmp|svg|eot|ttf|woff|woff2)$/i,use:[{// 把指定图片大小内的图片BASE64// 不再指定范围的采用file-loader进行处理// 符合规则的用url-loader处理,不符合的仍然用file-loader处理loader:'url-loader',options:{limit: 200 * 1024, // 小于200kb处理成BASE64// outputPath:'./images', // 图片编译后都放在统一的images文件下name:'images/[name].[hash].[ext]',esModule: false}}],include: path.resolve(__dirname,'src'),exclude: /node_modules/},// 处理HTML页面中的图片,按照上面的处理机制处理{test:/\.html$/,use:['html-withimg-loader']}//...]}}
真实项目中使用图片的地方
CSS中设置背景图
body{backgroundImage:url(./image/xxx.png) norepeat;}
JS中动态创建图片
如果网络地址直接写 如果相对地址,需要require导入否则找不到
let A = require('./static/play.png')let image = new Image;image.src = require('./static/play.png')document.body.appendChild(image)
- HTML中直接使用图片
<img src="./image/xxx.png"/>
9、三种方式引入第三方模块 expose-loader
1. expose-loader暴露全局window => import $ from 'expose-loader?$!jQuery'2. providePlugin给每个人提供一个$ =>plugins:[new webpack.ProvidePlugin({ // 在每个模块中都注入$$: 'jquery'}) ]3. 引入但是不加到打包后的文件中去externals: { // 引入cdn jquery 不打包jquery'jquery':'$'}
10、基于babel实现ES6的转换和ESLint语法检测
文档 https://babeljs.io/ https://eslint.org/ 安装 npm i babel-loader @babel/core @babel/preset-env -D npm i @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/plugin-transform-runtime-D npm i @babel/runtime @babel/polyfill -S npm i eslint-loader -D
默认情况下,webpack只是把各版本的代码合并压缩,对于JS并没有左其他处理,并没有兼容ES6等,需要额外处理 => babel
webpack.config.js
module.exports = {//...module: {rules: [// 处理JS//...{test: /\.(jsx?)$/i,use: [{loader: 'babel-loader',options: {presets: ['@babel/preset-env', //=> ES6 转成 ES5'@babel/preset-react' //=> 支持 React],//=> 基于插件处理ES6、ES7中的CLASS的特殊语法plugins: [['@babel/plugin-proposal-decorators',{ legacy: true },],['@babel/plugin-proposal-class-properties', { loose: true },],'@babel/plugin-transform-runtime',],},},// 开启语法检测"eslint-loader"],include: path.resolve(__dirname, 'src'),exclude: /node_modules/,},//...]}}
main.js
let [a,b] = [10,20];console.log(a,b)
11、设置sourceMap
// 增加映射文件,帮我们调试源代码devtool: 'source-map' // 产生单独文件, 增加映射,告诉我们错误的行和列 大和全devtool: 'eval-source-map' // 不会产生单独的文件,但是可以找到错误的行和列devtool: 'cheap-module-source-map' // 产生文件 不会找到行列devtool: 'cheap-module-eval-source-map' // 不产生文件 找到行 不找列// 开发环境推荐module.exports = {devtool: 'cheap-module-eval-source-map'}// 生产环境推荐module.exports = {devtool: 'cheap-module-source-map'}
12、 watch监控
实时打包 监控文件 ,每次可以看打包出来的文件 devServer打包的在内存没发看到
module.exports = {watch: true,watchOptions:{poll: 1000, // 每秒询问一下是不是更新aggreatment: 500, // 防抖 一致输入代码 打包ignored: /node_modules/ // 忽略哪个文件不监控}}
12、 resolve设置 解析第三方包
module.exports = {resolve:{modules: [path.resolve('node_moudles')],// 扩展名 此时在引入可以不加后缀名extensions:['.js','.css','.vue'],// mainFiels:['style','main'],// mainFiles:[], // 入口文件的名字 index.jsalias: { // 别名 vue ...bootstrap: 'bootstrap/dist/css/bootstrap.css'}}}
13、 快速开发
初始化
npm init -ynpm i webpack@4.44.2 webpack-cli@3.3.11 -D
安装
npm i html-webpack-plugin --save-devnpm i webpack-dev-server --save-devnpm i clean-webpack-plugin --save-devnpx webpack-dev-servernpm install css-loader style-loader less less-loader autoprefixer postcss-loader --save-devnpm i mini-css-extract-plugin --save-devnpm i optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin terser-webpack-plugin -Dnpm i file-loader url-loader html-withimg-loader -Dnpm i babel-loader @babel/core @babel/preset-env -Dnpm i @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/plugin-transform-runtime -Dnpm i @babel/runtime @babel/polyfill -Snpm i eslint-loader -Dnpm i expose-loader -D
webpack.config.js
const path = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');const { CleanWebpackPlugin } = require('clean-webpack-plugin');const MiniCssExtractPlugin = require('mini-css-extract-plugin');const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');const htmlPlugins = ['index', 'login'].map((item) => {return new HtmlWebpackPlugin({template: `./public/${item}.html`,filename: `${item}.html`,chunks: [item], // 设置多入口时的打包的哪个js进来,不写全部引入minify: {collapseWhitespace: true, // 去除空格removeComments: true, // 去掉注释removeAttributeQuotes: true, // 去除属性的双引号removeEmptyAttributes: true, // 去除空属性removeEmptyElements: true,},});});module.exports = {// 设置编译的入口文件mode: 'production',devtool: 'cheap-module-eval-source-map'// entry: './src/main.js',entry: {// jquery: 'jquery',index: './src/main.js',login: './src/login.js',},// 设置编译的出口文件output: {// 编译后的文件filename: '[name].[hash].min.js',path: path.resolve(__dirname, 'build'),},// 配置devServerdevServer: {// 端口port: 3000,// 开启GZIP压缩compress: true,// 显示编译进度progress: true,// 指定访问资源目录contentBase: path.resolve(__dirname, 'build'),// 自动打开浏览器open: true,// 开启热更新hot: true,// 请求代理// proxy: {// '/': {// target: 'http://localhost:8888',// secure: false, // true 为https , false 为http// changeOrigin: true, // 把请求头当中的host值改为服务器地址// },// },},// 设置优化项optimization: {// 设置压缩方式// minimize: true,minimizer: [//=> 压缩CSS(但是必须指定JS压缩方式)new OptimizeCssAssetsWebpackPlugin(),//=> 压缩JS 下面两个用一个即可new UglifyjsWebpackPlugin({cache: true, // 是否使用缓存parallel: true, // 是否是并发编译sourceMap: true, // 启动远吗映射 (方便调试)})],},module: {// 模块规则,使用加载器,从右向左执行,从下向上执行rules: [// 处理CSS{test: /\.(css|less)$/i, // 基于正则处理use: [// 'style-loader', // css插入到HEAD中MiniCssExtractPlugin.loader, // 处理less的文件 使用插件的loader,抽离css'css-loader', // 编译解析@import/URL这种语法'postcss-loader', // 设置前缀,兼容css3写法{loader: 'less-loader',options: {// 加载器额外配置},},],},// 处理图片{test: /\.(png|jpe?g|gif|ico|bmp|svg|eot|ttf|woff|woff2)$/i,use: [{// 把指定图片大小内的图片BASE64// 不再指定范围的采用file-loader进行处理// 符合规则的用url-loader处理,不符合的仍然用file-loader处理loader: 'url-loader',options: {limit: 1 * 1024, // 小于200kb处理成BASE64outputPath: './images', // 图片编译后都放在统一的images文件下name: '[name].[hash].[ext]',esModule: false,// publicPath: 'http://www.rockshang.cn' // 加CDN前缀},},],include: path.resolve(__dirname, 'src'),exclude: /node_modules/,},// 处理HTML页面中的图片,按照上面的处理机制处理{test: /\.html$/,use: ['html-withimg-loader'],},// 处理JS{test: /\.(jsx?)$/i,use: [{loader: 'babel-loader',options: {presets: [//=> ES6 转成 ES5'@babel/preset-env',],//=> 基于插件处理ES6、ES7中的CLASS的特殊语法plugins: [['@babel/plugin-proposal-decorators',{legacy: true,},],['@babel/plugin-proposal-class-properties',{loose: true,},],'@babel/plugin-transform-runtime',],},},// 开启语法检测"eslint-loader"],include: path.resolve(__dirname, 'src'),exclude: /node_modules/,},],},externals: { // 引入cdn jquery 不打包jquery'jquery':'$'}plugins: [new webpack.ProvidePlugin({ // 在每个模块中都注入$$: 'jquery'}),// new HtmlWebpackPlugin({// // 模版路径// template: './public/index.html',// // 编译后生成的文件名// filename: 'index.html',// // 是否把编译后的资源文件导入页面中都设置HASH(清缓存,和output中设置HASH值是一样的, 和output设置HASH是一样的效果,只要设置一个地方即可)// // hash: true, // 和output的HASH设置,设置一个即可// // 把模版中的HTML代码也进行压缩编译配置// // https://github.com/kangax/html-minifier// minify: {// collapseWhitespace: true, // 去除空格// removeComments: true, // 去掉注释// removeAttributeQuotes: true, // 去除属性的双引号// removeEmptyAttributes: true, // 去除空属性// removeEmptyElements: true,// },// }),// 多入口文件的处理...htmlPlugins,new CleanWebpackPlugin(),new MiniCssExtractPlugin({filename: '[name].[hash].min.css',}),],};
package.json
{"name": "weback","version": "1.0.0","description": "","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1","serve": "webpack-dev-server","build": "webpack --config webpack.config.js","dev": "webpack --config webpack.config.dev.js","prod": "webpack --config webpack.config.prod.js"},"keywords": [],"author": "","license": "ISC","devDependencies": {"@babel/core": "^7.12.9","@babel/preset-env": "^7.12.7","autoprefixer": "^10.0.3","babel-loader": "^8.2.2","clean-webpack-plugin": "^3.0.0","css-loader": "^5.0.1","eslint-loader": "^4.0.2","file-loader": "^6.2.0","html-webpack-plugin": "^4.5.0","html-withimg-loader": "^0.1.16","less": "^3.12.2","less-loader": "^7.1.0","mini-css-extract-plugin": "^1.3.1","optimize-css-assets-webpack-plugin": "^5.0.4","postcss-loader": "^4.1.0","style-loader": "^2.0.0","terser-webpack-plugin": "^5.0.3","uglifyjs-webpack-plugin": "^2.2.0","url-loader": "^4.1.1","webpack": "^4.44.2","webpack-cli": "^3.3.11","webpack-dev-server": "^3.11.0"},"browserslist": ["> 0.1%","last 10 versions"],"dependencies": {"@babel/polyfill": "^7.12.1","@babel/runtime": "^7.12.5"}}
postcss.config.js
module.exports = {plugins:[require('autoprefixer')]}
项目结构

14、webpack的优化
14-1、 noParse 不去匹配依赖项 如jQuery , exclude排除node_modules
const path = require('path');module.exports = {mode: 'production',entry: './src/main.js',// 设置编译的出口文件output: {// 编译后的文件filename: '[name].[hash].min.js',path: path.resolve(__dirname, 'build'),},module: {noParse:/jQuery/, // 不去解析jQueryrules: [// 处理JS{test: /\.(jsx?)$/i,use: [{loader: 'babel-loader',options: {presets: ['@babel/preset-env','@babel/preset-react'],},}],include: path.resolve(__dirname, 'src'),exclude: /node_modules/,},],},plugins: [],};
14-2、 webpack.IgnorePlugin(/.\/locale/,/moment/) 忽略某些包
import 'moment/locale/zh-cn' // 手动引入中文包plugins: [new webpack.IgnorePlugin(/\.\/locale/,/moment/) // 忽略这个包],
14-3、 DLLReferencePlugin 动态链接库
先去查找清单,没有再去打包react,react-dom @babel/preset-react
动态链接库,不用每次打包react,react库 , 大大提高开发效率
使用动态链接库 优化本地webpack打包体验
package.json
"dll": "npx webpack --config webpack.dll.config.js"
import React from ‘react’ import ReactDOM from ‘react-dom’,
ReactDOM.render(
hello world
)
webpack.config.react.js
let path = require('path')let webpack = require('webpack')module.exports = {mode:'development',entry:{react:['react','react-dom']},output:{filename:'_dll_[name].js', // 产生的文件名path:path.resolve(__dirname,'dist/dll'),library:'_dll_[name]', // _dll_react// libraryTarget:'var' // commonjs umd var this},plugins:[new webpack.DllPlugin({name:'_dll_[name]',path:path.resolve(__dirname,'dist/dll','manifest.json')})]}
在html文件中引入
<script src="/_dll_react.js"></script>
先去链接库找,找不到在去打包
webpack配置 webpack.config.js
plugins:[new webpack.DllReferencePlugin({manifest: path.resolve(__dirname,'dist','manifest.json')})]
14-4、 happypack 可以实现多线程 来打包 进程
npm i happypack
let Happypack = require('happypack')module.exports = {//...module: {rules: [// 处理JS//...{test: /\.js$/,include: path.resolve(__dirname, 'src'),exclude: /node_modules/,use: 'Happypack/loader?id=js',},{test: /\.css$/,include: path.resolve(__dirname, 'src'),exclude: /node_modules/,use: 'Happypack/loader?id=css',},//...]},plugins:[new Happypack({id:'js',use:[{loader: 'babel-loader',options: {presets: ['@babel/preset-env','@babel/preset-react']}}]}),new Happypack({id:'css',use:['style-loader','css-loader']})]}
14-5、 webpack自带的优化
1、 tree-shaking 把没用的代码自动删除上 只能import语法
let sum = (a,b) => a + b + ‘sum’ let minus = (a,b) => a - b + ‘minus’ export { sum , minus }
import calc from ‘./test’
2、 scope hosting 作用域提升
在webpack中会自动省略一些可以简化的代码,将一些计算提前计算,简化一些代码
let a =1 , b =3, c =3 ,d =a+b+c; console.log(d,’——-‘)
14-6、提取公共代码 splitChunks
webpack.config.js
optimization:{ // 优化项splitChunks:{ // 分割代码块 多页!cacheGroups:{ // 缓存组common:{ // 公共的模块chunks:'initial',minSize:0, // 大小minChunks:2 // 用了多少次},vendor:{ // 抽离第三方模块 如jQuerypriority:1, // 提高抽离权重,先抽离这个模块test:/node_modules/, // 把抽象代码抽离chunks:'initial',minSize:0, // 大小minChunks:2 // 用了多少次}}}}
14-7、懒加载 靠的就是import语法
点击按钮在加载资源
npm i @babel/plugin-syntax-dynamic-import -D 加到插件预设里
export default 'xxxxyyyy1111'let button = document.createElement('button')button.addEventListener('click',function(){// es6 草案语法import('./source.js').then(data=>{console.log(data.default)})})
14-8、热更新插件
webpack.config.js
devServer:{hot:true, // 启动热更新port: 3000,open: true,contentBase: './dist'}...plugins:[new webpack.NamedModulesPlugin(), // 打印更新的模块路径new webpack.HotModuleReplacementPlugin() // 热更新插件]
index.js
// source.jsexport default 'ssss'// index.jsimport str from './source';console.log(str)if(module.hot){module.hot.accept('./source',()=>{require('./source')console.log('文件更新了')})}
14-9、PWA 离线应用
webpack.config.js
6、PWA 离线技术访问```js//webpack.config.jsconst WorkboxWebpackPlugin = require("workbox-webpack-plugin");plugins: [new MiniCssExtractPlugin({filename: "css/style.[contenthash:10].css",}),new OptimizeCssAssetsWebpackPlugin(),new htmlWebpackPlugin({filename: "index.html",template: "./public/index.html",minify: {//压缩htmlcollapseWhitespace: true,removeComments: true,},}),new WorkboxWebpackPlugin.GenerateSW({clientsClaim: true, //帮助service-worker快速启动skipWaiting: true, //删除旧的service-worker//生成service-workder.js}),];//入口文件if ("serviceWorker" in navigator) {window.addEventListener("load", () => {navigator.serviceWorker.register("./service-worker.js").then(() => {console.log("service注册成功了~");}).catch(() => {console.log("service注册失败了~");});});}
```
