webpack是现阶段前端广为流传的一个打包工具!
webpack认为一切都是模块!
话不多说,放图:
那么,既然是打包,总的先知道从哪开始也就是入口,即配置项 entry,
有入口就有出口,即配置项 output
而对于非代码的东东。比如说图片,字体等webpack也会将其根据依赖关系不断的加入到依赖树中,进行打包。
entry的用法
1. 单入口:entry是一个字符串(单页应用)
module.exports = {
entry: './src/index.js'
}
2. 多入口:entry是一个对象(多页应用)
module.exports = {
entry: {
app: './src/app.js',
home: './src/home.js'
}
}
output的用法
module.exports = {
entry: {
app: './src/app.js',
home: './src/home.js'
},
output: {
filename: '[name].js',
path: __dirname + '/dist'
}
}
通过占位符确保输出文件名称的唯一性
核心:loaders
webpack开箱即用只支持js和json两种文件类型,那么其他类型的文件怎么办呢?
通过 loaders 可以很好的支持其他文件类型并且把它们转化成有效的模块,添加到依赖关系树中进行打包。
而loaders本身是一个函数,接受源文件作为参数,返回转换的结果。
名称 | 描述 |
babel-loader | 转换es6,es7等js新特性语法 |
css-loader | 支持.css文件的加载和解析,会对 @import 和 url() 进行处理,就像 js 解析 import/require() 一样 |
less-loader | 将less文件转为css文件 |
ts-loader | 将ts转为js |
file-loader | 进行图片,字体等的打包 |
raw-loader | 将文件以字符串的形式导入 |
thread-loader | 多进程打包js和css |
cache-loader | 在一些性能开销较大的 loader 之前添加 cache-loader,以便将结果缓存到磁盘里 |
style-loader | 把 CSS 插入到 DOM 中。配合css-loader一起使用 |
使用babel-loader,babel需要 .babelrc配置文件
loaders的用法
module.rules
允许你在 webpack 配置中指定多个 loader
const path = require('path')
module.exports = {
module: {
rules: [{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true
}
},
{ loader: 'sass-loader' }
]
}]
}
}
plugins用法
插件用于bundle文件的优化,资源管理和环境变量的注入,作用于整个构建过程。(用于webpack功能的增强)
任何laoders无法完成的操作,都可以用plugins执行
CommonsChunkPlugin | 将chunks相同的模块代码提取成公共js |
CleanWebpackPlugin | 清理构建目录 |
MiniCssExtractPlugin | 本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载。基于webpackV4.0 |
CopyWebpackPlugin | 将文件或者文件夹拷贝到构建的输出目录 |
HtmlWebpackPlugin | 创建html文件去承载输出的bundle |
UglifyjsWebpackPlugin | 压缩js |
ZipWebpackPlugin | 将打包的资源生成一个zip包 |
module.exports = {
plugins: [
new webpack.ProgressPlugin(),
new HtmlWebpackPlugin({ template: './src/index.html' }),
],
}
mode用法
mode用来指定当前的构建环境是:production, development, 还是none
设置mode可以使用webpack内置的函数,默认值为production
webpack的文件监听
文件监听是在源码发生变化时,自动重新构建出新的输出文件。
webpack开启监听模式,有两种方式:
1. 启动webpack命令时,加--watch参数
2. 在配置webpack.config.js文件中,设置watch为true
缺点是:每次需要手动的去刷新浏览器
文件监听原理:
轮询的去判断文件的最后编辑时间是否变化,某个文件发生了变化,并不会立刻告诉监听者,而是先缓存起来,等aggregateTimeout
module.exports = {
// 默认false
watch: true,
// 只有开启监听模式时,watchOptions才有意义
watchOptions: {
// 默认为空,忽略的文件或者文件夹,支持正则
ignored: /node_modules/,
// 监听到变化后会等300ms再去执行,默认300ms
aggregateTimeout: 300,
// 判断文件是否发生变化是通过不停的询问系统指定文件有没有变化实现的,默认每秒访问1000次
poll: 1000
}
}
热更新:webpack-dev-server (用于开发环境)
webpack-dev-server不会自动刷新浏览器,也不会输出文件,而是放在内存中。那么就需要配合 HotMoudleReplacementPlugin插件来实现。
const webpack = require('webpack')
module.exports = {
// 热更新用于开发环境
mode: "development",
plugins: [
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
hot: true
}
}
热更新还可以使用:webpack-dev-middleware 这个插件会将输出的文件传输给服务器,适用于更灵活的定制场景。
const express = require('express')
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')
const app = express()
const config = require('./webpack.config.js')
const compiler = webpack(config)
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath
}))
app.listen(3000, function() {
console.log('example app listening on port 3000')
})
热更新的原理
热更新包含启动阶段和更新阶段:
启动阶段即上图中的 1 2 A B
更新阶段即上图中的 1 2 3 4
文件指纹
什么是文件指纹呢?
相信很多人在鼠标右键点击 显示网页源代码 按钮之后 打开的页面中的最底部会看到类似于下面的这种的代码
图中的cd37ed75a9387c5b就是我们所说的指纹,具有唯一性。
即文件指纹就是打包后输出的文件名的后缀,可以用来控制版本。
常见的文件指纹:
- Hash:和整个项目的构建相关,只要项目文件有修改,整个项目构建的hash值就会更改
- Chunkhash: 和webpack打包的chunk有关,不同的entry会生成不同的chunkhash值
- Contenthash: 根据文件内容来定义hash,文件内容不变,则contenthash不变
用法:
// js的文件指纹设置 设置output的filename即可,使用[chunkhash]
// css的文件指纹设置 设置MiniCssExtractPlugin的filename,使用[contenthash]
// 图片等的文件指纹设置 设置file-loader的name,使用[hash](此处的hash是指文件内容的hash)
// 建议 mini-css-extract-plugin 与 css-loader 一起使用, 该插件与style-loaader互斥
module.exports = {
entry: {
app: './src/app.js',
home: './src/index.js'
},
output: {
filename: '[name]_[chunkhash:8].js',
path: __dirname + '/dist'
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name]_[contenthash:8].css'
})
],
module: {
rules: [{
test: /\.(png|svg|jpg|gif)$/,
use: [{
loader: 'file-loader',
options: {
name: 'img/[name]_[hash:8].[ext]'
}
}]
}, {
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
}]
}
}
图片等文件的一些占位符名称的含义表
占位符名称 | 含义 |
[ext] | 资源后缀名 |
[name] | 文件名称 |
[path] | 文件的相对路径 |
[folder] | 文件所在的文件夹 |
[contenthash] | 文件的内容hash,默认是md5生成 |
[hash] | 文件内容的hash,默认是md5生成 |
[emoji] | 一个随机的指代文件内容的emoji |
代码压缩
html压缩 css压缩 js压缩
webpack v4.0 内置了 uglifyjs-webpack-plugin插件针对js进行压缩
使用 optimize-css-assets-webpack-plugin 进行css文件的压缩,同时配合cssnano进行css预处理
使用 HtmlWebpackPlugin 进行html文件的压缩
module.exports = {
entry: {
app: './src/app.js',
home: './src/index.js'
},
output: {
filename: '[name]_[chunkhash:8].js',
path: __dirname + '/dist'
},
plugins: [
// 构建目录清理
new CleanWebpackPlugin()
// css 压缩
new OptimizeCSSAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor: require('cssnano')
}),
// html压缩
new HtmlWebpackPlugin({
template: path.join(__dirname, 'src/index.html'),
filename: 'index.html',
chunks: ['index'],
inject: true,
minify: {
html5: true,
collapseWhitespace: true,
preserveLineBreaks: false,
minifyCSS: true,
minifyJS: true,
removeComments: false
}
})
],
}
每次打包前清理构建目录:使用clean-webpack-plugin,默认会删除output指定的输出目录