”你负责开发,我负责打包”系列四

文章内容输出来源:拉勾大前端高薪训练营

- HMR

- 引入背景

	- webpack-dev-server自动刷新的问题

		- 自动刷新导致页面状态丢失

	- 期望的结果

		- 页面不刷新的前提下,模块也可以及时更新

	- 计算机行业经常听到热拔插的名词

		- 在一个正在运行的机器上随时插拔设备,机器运行状态不受影响,插上的设备可以立即开始工作

- 全称

	- Hot Module Replacement

		- 模块热替换

			- 应用运行过程中实时替换某个模块,应用运行状态不收影响

- 是webpack中最强大的功能之一
- 极大程度提高了开发者的效率
- 使用HMR

	- 开启HMR

		- 已集成在webpack-dev-server中
		- 两种方式

			- 命令行开启

				- webpack-dev-server --hot

			- 文件配置

				- const path = require ('path') 

const webpack = require (‘webpack’)
const { CleanWebpackPlugin }= require (‘clean-webpack-plugin’)
const HtmlWebpackPlugin = require (‘html-webpack-plugin’)
const CopyWebpackPlugin = require (‘copy-webpack-plugin’)

module.exports = {
mode: ‘none’,
// 指定webpack打包的入口路径,指定相对路径时,’./'不能省略
entry: ‘./src/main.js’,
// 设置输出文件的位置
output: {
// 设置输出文件名称
filename: ‘bundle.js’,
// 指定输出文件所在目录,不可使用相对路径
path: path.join(__dirname,‘output’)
// 默认值是个空字符串:代表网站的根目录。这里的/线不能省略
// publicPath: ‘dist/’,
},
//用于配置开发过程中的辅助工具。也就是与source-map功能相关的配置
devtool: ‘source-map’
// 专门用于webpack-dev-server做选项配置的
devServer: {
hot: true,
// 额外为开发服务器指定查找资源目录
contentBase: ‘./’,
proxy: {
‘/api’: {
// http://localhost:8080/api/users ⥤ https://api.github.com/api/users
target: ‘https://api.github.com’,
// http://localhost:8080/api/users ⥤ https://api.github.com/users
pathRewrite: {
‘^/api’: ‘’
},
// 不能使用localhost:8080 作为请求 GitHub的主机名
changeOrigin: true
}
}
},
module: {
// 针对于其他资源模块的加载规则的配置
rules: [
// 每个规则对象都需要配置两个属性: test和use
{
// 正则表达式,用于匹配我们在打包过程中所遇到的文件路径
test: /.cssKaTeX parse error: Expected 'EOF', got '}' at position 198: …] }̲, …/,
// 用来指定test匹配到的文件需要使用的loader,配置多个loader时执行顺序是从后往前执行
use: {
loader: ‘url-loader’,
options: {
limit: 10 * 1024, // 10KB,url-loader只将10KB以下的文件转换为Data URL形式,超过此大小的仍然交给file-loader完成加载
}
}
} ,
// 每个规则对象都需要配置两个属性: test和use
{
// 正则表达式,用于匹配我们在打包过程中所遇到的文件路径
test: /.htmlKaTeX parse error: Expected 'EOF', got '}' at position 171: …} }̲ , …/,
// 用来指定test匹配到的文件需要使用的loader,配置多个loader时执行顺序是从后往前执行
use: [
‘html-loader’,
‘./markdown-loader’,
]
}
]
},
plugins: [
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin(),
// 用于生成 index.html文件
new HtmlWebpackPlugin({
// 指定自动生成的html的标题
title: ‘Webpack Plugin Sample’,
// 设置元数据标签
meta: {
viewport: ‘width=device-width’
},
// 指定自动生成的html的模板文件
template: ‘./src/index.html’,
}) ,
// 用于生成 about.html文件
new HtmlWebpackPlugin({
// 设置生成html的文件名称,默认为index.html
filename: ‘about.html’,
}) ,
// 用于拷贝资源文件。在开发阶段最好不要使用这个插件。
// 开发中会频繁执行打包任务,假设如果拷贝的文件较多或比较大。
// 每次执行开销较大,并且打包速度也会降低。建议打生产包时再放开使用
//new CopyWebpackPlugin([
// 支持通配符
// ‘public/**’,
// 也支持相对路径
// ‘public’,
//]) ,
]
}

	- yarn webpack-dev-server --open

		- js还是会导致自动刷新页面

- webpack HMR的疑问❓

	- 为什么样式文件的热更新开箱即用❓

		- 因为style-loader实现了热替换逻辑

	- JS为啥不像css那样由某个Loader统一处理❓

		- JS代码无规律可循

	- 我的项目没有手动处理, JS照样可以热替换❓

		- 你使用了框架。通过脚手架创建的项目内部都集成了HMR方案

	- 总结

		- 我们需要手动处理JS模块更新后的热替换

- HMR APIS

	- JS模块的热替换

		- main.js

			- import createEditor from './editor' 

import background from ‘./better.png’
import ‘./global.css’
const editor = createEditor()
document. body.appendchild(editor)
const img = new Image()
img.src = background
document.body. appendchild(img)

module.hot.accept(’./editor’, () ⥤ {
// console.log(‘editor 模块更新了,需要这里手动处理热替换’)
const value = lastEditor. innerHTML
document.body.removechild(lastEditor)
const newEditor = createEditor()
newEditor.innerHTML = value
document.body.appendchild(newEditor)
lastEditor = newEditor
})
- yarn webpack-dev-server

				- OK~

	- 图片模块的热替换

		- import createEditor from './editor' 

import background from ‘./better.png’
import ‘./global.css’
const editor = createEditor()
document. body.appendchild(editor)
const img = new Image()
img.src = background
document.body. appendchild(img)

module.hot.accept(’./editor’, () ⥤ {
// console.log(‘editor 模块更新了,需要这里手动处理热替换’)
const value = lastEditor. innerHTML
document.body.removechild(lastEditor)
const newEditor = createEditor()
newEditor.innerHTML = value
document.body.appendchild(newEditor)
lastEditor = newEditor
})
module.hot.accept(’./better.png’, () ⥤ {
img.src = background
console.log(background)
})
- yarn webpack-dev-server

			- OK~

- HMR注意事项

	- 1,处理HMR的代码报错会导致自动刷新

		- 是因为使用了hot。可以考虑使用hotOnly,这样即使处理热替换的代码报错也不会自动刷新
		- hot: true  ⥤ hotOnly: true

	- 2,没启用HMR的情况下,HMR APIS 会报错

		- import createEditor from './editor' 

import background from ‘./better.png’
import ‘./global.css’
const editor = createEditor()
document. body.appendchild(editor)
const img = new Image()
img.src = background
document.body. appendchild(img)

module.hot && module.hot.accept(’./editor’, () ⥤ {
// console.log(‘editor 模块更新了,需要这里手动处理热替换’)
const value = lastEditor. innerHTML
document.body.removechild(lastEditor)
const newEditor = createEditor()
newEditor.innerHTML = value
document.body.appendchild(newEditor)
lastEditor = newEditor
})
module.hot && module.hot.accept(’./better.png’, () ⥤ {
img.src = background
console.log(background)
})

	- 3,代码中多了一些与业务无关的代码

		- 去掉热替换配置
		- yarn webpack
		- 查看打包文件

			- 发现: if(false){}

		- 总结: 不会有任何影响

- 生产环境优化

- 生产环境跟开发环境有着很大的差异

	- 生产环境注重运行效率
	- 开发环境只注重开发效率

- webpack4推出了mode的用法

	- none
	- development
	- production

- webpack也建议我们为不同的工作环境创建不同的配置
- 不同环境下的配置

	- 配置文件根据环境不同导出不同配置

		- const webpack = require( "webpack')

const CleanWebpackPlugin } = require("clean-webpack-plugin’)
const htmlWebpackPlugin = require(‘html-webpack-plugin’)
const CopywebpackPlugin = require(‘copy-webpack-plugin’)
module.exports = (env, argv) ⥤ {
const config = {
// 开发配置here
}

 if (env =production") {
   config.mode = 'production'
   config.devtool =false
   config.plugins =[
       ...config.plugins,
       new CleanWebpackPlugin()
       new CopywebpackPlugin(['public'])
   ]
}
return config

}
- 开发: yarn webpack --env development
- 生产: yarn webpack --env production

	- 一个环境对应一个配置文件

		- webpack.common.js
		- webpack.dev.js
		- webpack.prod.js

			- const common = require('./webpack. common')

const merge = require(‘webpack-merge’)
const CleanWebpackPlugin = require( ‘clean-webpack-plugin’)
const CopyWebpackPlugin = require(’ copy-webpack-plugin’)
module. exports = merge(common, {
mode: ‘production’,
plugins: [
new CleanWebpackPlugin()
new CopyWebpackPlugin([‘public’])
]
})

		- yarn add webpack-merge --dev
		- yarn webpack --config webpack.prod.js

	- DefinePlugin

		- 在webpack新增的production模式下面,内部就开启了很多通用的优化功能
		- 主要的优化配置之一
		- 为代码注入全局成员

			- 会注入:process.env.NODE_ENV

		- 启用

			- webpack.config.js

				- const webpack = require('webpack')

module. exports ={
mode: ‘none’,
entry: ‘./src/main.js’,
output: {
filename: 'bundle. js
},
plugins: [
new webpack.DefinePlugin({
API_BASE_URL: ‘https://api.example.com’
})
]
}

			- main.js

				-  console.Iog(API_BASE_URL)

			- yarn webpack

				- 打包后代码语法未通过
				- webpack.config.js

					- const webpack = require('webpack')

module. exports ={
mode: ‘none’,
entry: ‘./src/main.js’,
output: {
filename: 'bundle. js
},
plugins: [
new webpack.DefinePlugin({
API_BASE_URL: ‘“https://api.example.com”’
})
]
}
- const webpack = require(‘webpack’)
module. exports ={
mode: ‘none’,
entry: ‘./src/main.js’,
output: {
filename: 'bundle. js
},
plugins: [
new webpack.DefinePlugin({
API_BASE_URL:JSON.Stringify(‘https://api.example.com’)
})
]
}

				- yarn webpack

					- OK~

- Tree-shaking

	- 摇树🌲
	- 摇掉代码中未引用的部分

		- 即未引用代码(dead code)

	- webpack生产模式优化中就有这个功能

		- 检测未引用的代码并移除它们

	- 使用

		- components.js

			- export const Button =()⥤{
return document.createElement( 'button')
console. Log('dead-code')

}
export const Link =() ⥤{
return document.createELement(‘a’)
}
export const Heading = level ⥤ {
return document.createElement(‘h’ + level)
}

		- index.js

			-  import { Button } from './components' 

document.body.appendChild(Button())

		- yarn webpack --mode production

			- 经检查:未引用的代码被移除了

		- 需要注意

			- Tree Shaking不是指某个配置选项,而是一组功能搭配使用后的优化效果
			- 这个功能会在production模式自动开启

		- 非生产模式使用

			- webpack.config.js

				- module.exports = { 
 mode: 'none'
 entry: './src/index.js', 
 output: {
     filename: 'bundle.js'
 },
 optimization: {
     // 表示在输出结果中只导出那些外部使用了的成员,负责标记枯树叶
     usedExports: true,
     // 负责摇掉那些枯树叶
     minimize: true
 }

}
- yarn webpack

			- 合并模块函数(Scope Hoisting)

				- concatenateModules

					- module.exports = { 
 mode: 'none'
 entry: './src/index.js', 
 output: {
     filename: 'bundle.js'
 },
 optimization: {
     // 表示在输出结果中只导出那些外部使用了的成员,负责标记枯树叶
     usedExports: true,
     // 尽可能的将所有模块合并输出到一个函数中,
     // 这样既提升了运行效率,又减少了代码的体积
     //又称为作用域提升。webpack3提出的特性
     concatenateModules: true,
     // 负责摇掉那些枯树叶
     minimize: true
 }

}

			- Tree-shaking & Babel

				- 传言如果使用Babel,Tree-shaking会失效
				- Tree Shaking前提是ES Modules

					- 也就是由webpack打包的代码必须使用ESM
					- webpack在打包所有模块之前,先是将模块根据配置交给不同的Loader去处理。
					- 最后再将所有Loader处理的结果打包到一起
					- 为了转换代码中ECMAScript新特性

						- 很多时候选择babel-loader进行处理
						- babel-loader处理时可能产生这种转换

							- ES Modules⥤ CommonJS

				- webpack.config.js

					- module. exports ={
mode: 'none,
 entry: './src/index.js',
 output: {
     filename: 'bundle js
 },
 module: {
     rules: [
        {
          test:/\.js$/,
          use: {
             loader: 'babel-loader',
             options:{
                presets: ['@babel/preset-env']
              }
           },
           optimization: {
              //模快只导出被使用的成员
              usedExports: true
              //尽可能合并每一个模块到一个函数中
              // concatenateModules: true,
              //压缩输出结果
              // minimize: true
           }
         }
      ]
 }

}
- yarn webpack

						- Ok:Tree Shaking并未失效

							- 因为在最新版本的babel-loader中已自动帮我们关闭了ES Modues转换的插件

					- 强制使用ES Modules转换为CommonJS

						- module. exports ={
mode: 'none,
 entry: './src/index.js',
 output: {
     filename: 'bundle js
 },
 module: {
     rules: [
        {
          test:/\.js$/,
          use: {
             loader: 'babel-loader',
             options:{
                presets: [
                   ['@babel/preset-env', { modules: 'commonjs' }]
                ]
              }
           },
           optimization: {
              //模快只导出被使用的成员
              usedExports: true
              //尽可能合并每一个模块到一个函数中
              // concatenateModules: true,
              //压缩输出结果
              // minimize: true
           }
         }
      ]
 }

}
- yarn webpack

							- OK: Tree Shaking失效了

	- webpack 生产模式打包时自动开启

- sideEffects(副作用)

- webpack4中新增
- 允许通过配置的方式去标识代码是否有副作用,从而为tree Shaking提供更大的压缩空间
- 副作用是指模块执行时除了导出成员之外所作的事情
- 一般用于npm包标记是否有副作用
- Tree Shaking 跟 sideEffects并非因果关系,且二者并无什么关系
- webpack.config.js

	- module. exports ={
mode: 'none,
 entry: './src/index.js',
 output: {
     filename: 'bundle js
 },
 module: {
     rules: [
        {
          test:/\.js$/,
          use: {
             loader: 'babel-loader',
             options:{
                presets: [
                   ['@babel/preset-env', { modules: 'commonjs' }]
                ]
              }
           },
           optimization: {
              // 开启副作用特性
              sideEffects: true
              //模快只导出被使用的成员
              // usedExports: true
              //尽可能合并每一个模块到一个函数中
              // concatenateModules: true,
              //压缩输出结果
              // minimize: true
           }
         }
      ]
 }

}

- package.json

	- 添加sideEffects属性并设置为false

		- 标识当前package.json所影响的项目当中的所有代码都没有副作用

	- yarn webpack

		- Ok:成功去掉没有副作用的代码

- 注意

	- 使用sideEffects的前提就是确保你的代码真的没有副作用
	- package.json

		- "sideEffects": false ⥤ "sideEffects": [

“./src/extend.js”,
“*.css”
]

	- yarn webpack

		- OK: 有副作用的代码正常被打包

- Code Splitting (代码分包,代码分割)

- webpack打包弊端

	- 所有代码最终都被打包在一起
	- 导致bundle体积过大
	- 并非每个模块在启动时都是必要的
	- HTTP1.1缺陷

		- 同域并行请求限制
		- 每次请求都有一定的延迟
		- 请求的Header浪费带宽流量

- 解决:分包,按需加载

	- 多入口打包(Multi Entry)

		- 适用于多页应用程序

			- 一个页面对应一个大包入口
			- 不同页面的公共部分单独提取

		- 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’
},
module: {
rules: [
{
test: 八.csss/,
use: [
‘style-loader’,
‘css-loader’
]
}
]
},
plugins: {
new CleanWebpackPlugin()
new HtmlWebpackPlugin({
title: ‘Multi Entry’
template: ‘./src/index.html’,
filename: ‘index.html’
}),
new HtmlWebpackPlugin({
title: ‘Multi Entry’,
template: ‘./src/aibum. html’,
filename: 'album.html"
})
}
}
- yarn webpack

			- OK: 但是两个打包生成的html都引用了所有的模块
			- 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’
},
module: {
rules: [
{
test: 八.csss/,
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/aibum. html’,
filename: 'album.html",
chunks: [‘album’]
})
}
}
- yarn webpack

				- Ok~

		- 提取公共模块(Split Chunks)

			- 不同入口肯定会有公共模块
			- 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: {
chunks: ‘all’
}
},
module: {
rules: [
{
test: 八.csss/,
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/aibum. html’,
filename: 'album.html",
chunks: [‘album’]
})
}
}
- yarn webpack

				- Ok: 除了两个模块外也生成了公共模块

	- 动态导入(Dynamic Imports)

		- 按需加载

			- 加载数据(不做描述)
			- 加载模块

				- 需要用到某个模块时,再去加载这个模块

		- 动态导入的模块会被自动分包
		- 相对多入口打包,更为灵活
		- 使用

			- index.js

				- 静态导入

					- import posts from './posts/posts'

import album from ‘./album/album’
const render = () ⥤ {
const hash = window.location.hash || ‘posts’
const mainElement = document.queryselector(’.main’)
mainElement.innerHTML = ‘’
if (hash === ‘posts’) {
mainElement.appendchild(posts())
} else if {
mainElement.appendchild(album())
}
}
render()
window. addEventListener(‘hashchange’, render)
- 问题: 无论何时两个模块都会加载

				- 动态导入

					- // import posts from './posts/posts'

// import album from ‘./album/album’
const render = () ⥤ {
const hash = window.location.hash || ‘posts’
const mainElement = document.queryselector(’.main’)
mainElement.innerHTML = ‘’
if (hash === ‘posts’) {
// mainElement.appendchild(posts())
import(’./posts/posts’).then(({ default: posts })⥤{
mainElement.appendChild(posts())
})
} else if {
// mainElement.appendchild(album())
import(’./album/album’).then(({ default: album })⥤{
mainElement.appendChild(album())
})
}
}
render()
window. addEventListener(‘hashchange’, render)
- yarn webpack

						- OK: 打包后生成了三个包,一个主入口,一个按需加载的,一个公共的

- 魔法注释

- // import posts from './posts/posts'

// import album from ‘./album/album’
const render = () ⥤ {
const hash = window.location.hash || ‘posts’
const mainElement = document.queryselector(’.main’)
mainElement.innerHTML = ‘’
if (hash === ‘posts’) {
// mainElement.appendchild(posts())
import(/* webpackChunkName: ‘posts’ /’./posts/posts’).then(({ default: posts })⥤{
mainElement.appendChild(posts())
})
} else if {
// mainElement.appendchild(album())
import(/
webpackChunkName: ‘album’ */’./album/album’).then(({ default: album })⥤{
mainElement.appendChild(album())
})
}
}
render()
window. addEventListener(‘hashchange’, render)
- yarn webpack

	- OK~

- 按需打包到同一个文件中

	- // import posts from './posts/posts'

// import album from ‘./album/album’
const render = () ⥤ {
const hash = window.location.hash || ‘posts’
const mainElement = document.queryselector(’.main’)
mainElement.innerHTML = ‘’
if (hash === ‘posts’) {
// mainElement.appendchild(posts())
import(/* webpackChunkName: ‘components’ /’./posts/posts’).then(({ default: posts })⥤{
mainElement.appendChild(posts())
})
} else if {
// mainElement.appendchild(album())
import(/
webpackChunkName: ‘components’ */’./album/album’).then(({ default: album })⥤{
mainElement.appendChild(album())
})
}
}
render()
window. addEventListener(‘hashchange’, render)
- yarn webpack

		- Ok: 生成components文件和一个公共模块文件

- 提取CSS到单个文件中

- MiniCssExtractPlugin

	- 可以将css代码从打包结果中提取出来的插件
	- 用它可以实现css模块的按需加载
	- 使用

		- yarn add mini-css-extract-plugin --dev
		- webpack.config.js

			- const { CleanWebpackPlugin }  =require("clean-webpack-plugin') 

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)
const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)
module. exports ={
mode: ‘none’
entry: {
index:’./src/index. js’,
album: ‘./src/album. js’
},
output: {
filename: ‘[name].bundle. js’
},
module: {
rules: [
{
test: 八.csss/,
use: [
// ‘style-loader’, // 将样式通过style标签注入html中
MiniCssExtractPlugin.loader, //用于 将单独打包的css文件通过link方式注入
‘css-loader’
]
}
]
},
plugins: {
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: ‘Dynamic Import’
template: ‘./src/index.html’,
filename: ‘index.html’
})
new MiniCssExtractPlugin(),
}
}
- yarn webpack

				- OK~

- OptimizeCssAssetsWebpackPlugin(压缩输出的CSS文件)

	- yarn add optimize-css-assets-webpack-plugin --dev
	- webpack.config.js

		- const { CleanWebpackPlugin }  =require("clean-webpack-plugin') 

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)
const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)
const OptimizeCssAssetsWebpackPlugin = require(‘optimize-css-assets-webpack-plugin’)
module. exports ={
mode: ‘none’
entry: {
index:’./src/index. js’,
album: ‘./src/album. js’
},
output: {
filename: ‘[name].bundle. js’
},
module: {
rules: [
{
test: 八.csss/,
use: [
// ‘style-loader’, // 将样式通过style标签注入html中
MiniCssExtractPlugin.loader, //用于 将单独打包的css文件通过link方式注入
‘css-loader’
]
}
]
},
plugins: {
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: ‘Dynamic Import’
template: ‘./src/index.html’,
filename: ‘index.html’
}),
new MiniCssExtractPlugin(),
new OptimizeCssAssetsWebpackPlugin(),
}
}
- yarn webpack

			- OK~

	- 推荐用法

		- webpack.config.js

			- const { CleanWebpackPlugin }  =require("clean-webpack-plugin') 

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)
const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)
const OptimizeCssAssetsWebpackPlugin = require(‘optimize-css-assets-webpack-plugin’)
module. exports ={
mode: ‘none’
entry: {
index:’./src/index. js’,
album: ‘./src/album. js’
},
output: {
filename: ‘[name].bundle. js’
},
optimization: {
minimizer: [
new OptimizeCssAssetsWebpackPlugin()
]
},
module: {
rules: [
{
test: 八.csss/,
use: [
// ‘style-loader’, // 将样式通过style标签注入html中
MiniCssExtractPlugin.loader, //用于 将单独打包的css文件通过link方式注入
‘css-loader’
]
}
]
},
plugins: {
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: ‘Dynamic Import’
template: ‘./src/index.html’,
filename: ‘index.html’
}),
new MiniCssExtractPlugin(),
// new OptimizeCssAssetsWebpackPlugin(),
}
}
- yarn webpack

				- OK: JS未自动压缩了:(
				- const { CleanWebpackPlugin }  =require("clean-webpack-plugin') 

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)
const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)
const OptimizeCssAssetsWebpackPlugin = require(‘optimize-css-assets-webpack-plugin’)
const TerserWebpackPlugin = require(‘terser-webpack-plugin’)
module. exports ={
mode: ‘none’
entry: {
index:’./src/index. js’,
album: ‘./src/album. js’
},
output: {
filename: ‘[name].bundle. js’
},
optimization: {
minimizer: [
new TerserWebpackPlugin(),
new OptimizeCssAssetsWebpackPlugin()
]
},
module: {
rules: [
{
test: 八.csss/,
use: [
// ‘style-loader’, // 将样式通过style标签注入html中
MiniCssExtractPlugin.loader, //用于 将单独打包的css文件通过link方式注入
‘css-loader’
]
}
]
},
plugins: {
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: ‘Dynamic Import’
template: ‘./src/index.html’,
filename: ‘index.html’
}),
new MiniCssExtractPlugin(),
// new OptimizeCssAssetsWebpackPlugin(),
}
}
- yarn add terser-webpack-plugin --dev

- 输出文件名Hash(substitution)

- 一般部署前端资源文件时,都会启用服务器的静态资源缓存

	- 这样对于用户的浏览器而言,可以缓存住静态资源,后续不会再发起静态资源请求了
	- 提高了应用响应速度
	- 开启客户端静态资源缓存的问题

		- 如果缓存策略中缓存失效时间过短,效果不太明显
		- 过期时间设置比较长

			- 应用更新后重新部署,没法及时看见更新效果

- 生产模式下,文件名使用Hash

	- 生产模式下,文件名使用Hash
	- 不用担心文件更新后的问题
	- 几种hass

		- 普通hash

			- const { CleanWebpackPlugin }  =require("clean-webpack-plugin') 

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)
const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)
module. exports ={
mode: ‘none’
entry: {
index:’./src/index. js’,
album: ‘./src/album. js’
},
output: {
filename: ‘[name]-[hash].bundle. js’
},
module: {
rules: [
{
test: 八.csss/,
use: [
// ‘style-loader’, // 将样式通过style标签注入html中
MiniCssExtractPlugin.loader, //用于 将单独打包的css文件通过link方式注入
‘css-loader’
]
}
]
},
plugins: {
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: ‘Dynamic Import’
template: ‘./src/index.html’,
filename: ‘index.html’
})
new MiniCssExtractPlugin({
filename: ‘[name]-[hash].bundle.css’
}),
}
}
- 整个项目级别的,项目中任何一个地方发生改动,hash值会发生变化

		- chunk hash

			- const { CleanWebpackPlugin }  =require("clean-webpack-plugin') 

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)
const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)
module. exports ={
mode: ‘none’
entry: {
index:’./src/index. js’,
album: ‘./src/album. js’
},
output: {
filename: ‘[name]-[chunkhash].bundle. js’
},
module: {
rules: [
{
test: 八.csss/,
use: [
// ‘style-loader’, // 将样式通过style标签注入html中
MiniCssExtractPlugin.loader, //用于 将单独打包的css文件通过link方式注入
‘css-loader’
]
}
]
},
plugins: {
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: ‘Dynamic Import’
template: ‘./src/index.html’,
filename: ‘index.html’
})
new MiniCssExtractPlugin({
filename: ‘[name]-[chunkhash].bundle.css’
}),
}
}
- Chunck级别的hash,一旦chunk涉及内容改变,对应chunk的hash会发生变化
- 相对普通hash,chunk hash更精准一些。

		- content hash

			- 文件级别的hash,是根据文件内容生成的hash
			- 相比普通hash 和 chunk hash,content hash是更优的hash方式

				- 最适合解决缓存问题的

			- const { CleanWebpackPlugin }  =require("clean-webpack-plugin') 

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)
const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)
module. exports ={
mode: ‘none’
entry: {
index:’./src/index. js’,
album: ‘./src/album. js’
},
output: {
filename: ‘[name]-[contenthash].bundle. js’
},
module: {
rules: [
{
test: 八.csss/,
use: [
// ‘style-loader’, // 将样式通过style标签注入html中
MiniCssExtractPlugin.loader, //用于 将单独打包的css文件通过link方式注入
‘css-loader’
]
}
]
},
plugins: {
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: ‘Dynamic Import’
template: ‘./src/index.html’,
filename: ‘index.html’
})
new MiniCssExtractPlugin({
filename: ‘[name]-[contenthash].bundle.css’
}),
}
}

	- 控制hash长度

		- const { CleanWebpackPlugin }  =require("clean-webpack-plugin') 

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)
const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)
module. exports ={
mode: ‘none’
entry: {
index:’./src/index. js’,$$
album: ‘./src/album. js’
},
output: {
filename: ‘[name]-[contenthash:8].bundle. js’
},
module: {
rules: [
{
test: 八.csss/,
use: [
// ‘style-loader’, // 将样式通过style标签注入html中
MiniCssExtractPlugin.loader, //用于 将单独打包的css文件通过link方式注入
‘css-loader’
]
}
]
},
plugins: {
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: ‘Dynamic Import’
template: ‘./src/index.html’,
filename: ‘index.html’
})
new MiniCssExtractPlugin({
filename: ‘[name]-[contenthash:8].bundle.css’
}),
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值