一、webpack是什么?
webpack是一种前端资源构建工具,静态模块打包器。前端所有的资源文件都会被当做模块,根据资源依赖关系,最后打包出一个或
多个bundle(静态资源)
二、webpack五个核心概念
1、entry
打包文件入口,分析构建依赖图
2、output
打包文件出口(指定文件夹输出到哪里,怎样命名文件名)
3、loader
处理一些非JavaScript文件,如图片
4、plugins
可执行范围更广的任务, 比如打包优化、压缩、定义环境变量
5、mode
开发环境或者生产环境(development or prodution)
代码:
const {resolve} = require('path')
module.exports = {
// 入口起点
entry: './src/index.js',
// 输出
output: {
filename: 'build.js', // 输出路径
path: resolve(__dirname, 'build') // dirname 为nodejs变量名,代表当前文件目录的绝对路径
},
module: {
rules:[
{
test: /\.css$/, //匹配哪些文件
// 使用哪些loader,执行顺数重下到上
use: [
'style-loader', //创建style标签, 将js中的样式插入head中生效
'css-loader' //将css文件变成commonjs模块加载js中,内容是样式字符串
]
},
{
test: /\.less$/, //匹配哪些文件
// 使用哪些loader,执行顺数重下到上
use: [
'style-loader', //创建style标签, 将js中的样式插入head中生效
'css-loader', //将css文件变成commonjs模块加载js中,内容是样式字符串
'less-loader' // 将less文件编译为css文件
]
}
]
},
plugins: [],
mode: 'development'
// mode: 'production'
}
三、打包css、less等样式文件
{
test: /\.css$/, //匹配哪些文件
// 使用哪些loader,执行顺序重下到上
use: [
'style-loader', //创建style标签, 将js中的样式插入head中生效
'css-loader' //将css文件变成commonjs模块加载js中,内容是样式字符串
]
},
{
test: /\.less$/, //匹配哪些文件
// 使用哪些loader,执行顺数重下到上
use: [
'style-loader', //创建style标签, 将js中的样式插入head中生效
'css-loader', //将css文件变成commonjs模块加载js中,内容是样式字符串
'less-loader' // 将less文件编译为css文件
]
}
如果是其他样式文件需要下载不同的loader
四、打包html
需要安装插件html-webpack-plugin
引入const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins:[
new HtmlWebpackPlugin({
template: './src/index.html'
}),
]
五、打包图片
{
test: /\.(jpg|png|gif)$/,
// 下载url-loader, file-loader
loader: 'url-loader',
options: {
// 图片小于8kb就会被base64处理, 优点:减少服务器压力;缺点:图片体积会变大。一般用于小图片
limit: 30 * 1024,
esModule: false,
name: '[hash:10].[ext]'
}
},
{
test: /\.html$/,
// 处理html里的img
loader: 'html-loader'
}
六、打包其他资源(字体图标等)
{
exclude: /\.(html|js|css|less|jpg|png|gif)$/,
loder: 'file-loader',
options: {
name: '[hash:10].[ext]'
}
}
七、devServer
// 只会在内存中编译,不会有任何输出
// devServer启动指令: npx webpack-dev-server
devServer: {
// 开启服务器,自动化启动默认浏览器,刷新浏览器等
contentBase: resolve(__dirname, 'build'), // 构建之后的路径
port: 3000, // 端口号
open: true, // 自动打开默认浏览器
compress: true // 开启gzip压缩
}
八、提取js文件中的css为单独文件
需要安装插件mini-css-extract-plugin
引入const MiniCssExtractPlugin = require(mini-css-extract-plugin)
{
test: /\.css$/,
use:[
'MiniCssExtractPlugin.loader' // 取代style-loader
'css-loader',
]
},
plugins:[
new MiniCssExtractPlugin({
filename: 'css/build.css' // 输出文件重命名
})
]
九、css兼容性处理
需要安装postcss-loader postcss-preset-env
{
test: /\.css$/,
use:[
'MiniCssExtractPlugin.loader' // 取代style-loader
'css-loader',
],
// 修改loader配置
loader: {
ident: postcss,
plugins: () => [
// postcss的插件,帮助postcss找到package.json文件里的browsersList的配
置,通过配置加载指定的css兼容样式
requrie('postcss-preset-env')()
]
}
}
"browsersList": {
"development": [
"last 1 chorme version",
"last 1 firefox version",
"last 1 safari version"
],
"production": [
"> 0.2%",
"no dead",
"not op_mini all"
]
}
默认打包是生产环境,如果需要看开发环境,须设置process.env.NODE_ENV = 'development'
十、css压缩
需要安装插件OptimizeCssAssetsWebpackPlugin
引入const OptimizeCssAssetsWebpackPlugin = require(optimize-css-assets-webpack-plugin)
plugins:[
new OptimizeCssAssetsWebpackPlugin()
]
十一、js兼容
1、基本js兼容,babel-loader @babel/core @babel/preset-env,不能处理高级语法如:promise
2、全部兼容@babel-polyfill,但体积过大 // 安装后直接引入到入口文件
3、按需处理 core.js
{
test: /\.js$/,
exclude: /node_modules/
loader: 'babel-loader', // 处理基本语法
options: {
presets: ['@babel/preset-env'],
// 按需处理js
presets: [
[
'@babel/preset-env',
{
useBuildIns: usage, // 表示按需加载
coreJs: {
version: 3 // corejs版本
}
// 兼容到那个指定浏览器版本
targets: {
chrme: '60',
ie: '9',
firefox: '60',
edge: '17',
safari: '10'
}
}
]
]
}
}
十二、压缩html,js
生产环境下会自动压缩js,所以设置mode: 'production'
压缩html需要安装插件html-webpack-plugin
引入const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins:[
new HtmlWebpackPlugin({
template: './src/index.html',
miniy: {
//移除空格
collaspeWritespace: true,
//移除注释
removeComments: true
}
}),
]
十三、生产环境基本配置
const {resolve} = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin') // 压缩css
const HtmlWebpackPlugin = require('html-webpack-plugin')
process.env.NODE_ENV = 'production' // 配置nodejs环境变量
const commonCssLoader = [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: {
ident: postcss,
plugins: () => [
// postcss的插件,帮助postcss找到package.json文件里的browsersList的配置,通过配置加载指定的css兼容样式
requrie('postcss-preset-env')()
]
}
}
]
module.exports = {
entry: './src/index.js',
output: {
filename: 'build.js',
path: resolve(__dirname, 'build')
},
module: {
rules: [
{
test: /\.css$/,
use:[...commonCssLoader]
},
{
test: /\.less$/,
use:[
...commonCssLoader,
'less-loader'
]
},
// 在package.json中eslintConfig --> airbnb
{
test: /\.js$/,
exclude: /node_modules/,
// 优先执行
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// 按需处理js
presets: [
[
'@babel/preset-env',
{
useBuildIns: usage, // 表示按需加载
coreJs: {
version: 3 // corejs版本
},
// 兼容到那个指定浏览器版本
targets: {
chrme: '60',
ie: '9',
firefox: '60',
edge: '17',
safari: '10'
}
}
]
]
}
},
{
test: /\.(jpg|png|gif)$/,
loder: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
esmodule: false,
outputPath: 'imgs'
}
},
{
test: /\.html$/,
loder: 'html-loader'
},
{
exclude: /\.(html|js|css|less|jpg|png|gif)$/,
loder: 'file-loader',
options: {
name: '[hash:10].[ext]',
outputPath: 'others'
}
}
]
},
plugins:[
new HtmlWebpackPlugin({
template: './src/index.html',
miniy: {
//移除空格
collaspeWritespace: true,
//移除注释
removeComments: true
}
}),
new MiniCssExtractPlugin({
filename: 'css/build.css'
}),
new OptimizeCssAssetsWebpackPlugin()
],
mode: 'production'
}
十四、开发环境优化打包速度
HMR(hot module replacement)热模块替换,一个模块修改只打包替换对应修改的模块,极大的提升构建速度。
css样式文件只需开启devServer hot配置项为true
devServer: {
// 开启服务器,自动化启动默认浏览器,刷新浏览器等
contentBase: resolve(__dirname, 'build'), // 构建之后的路径
port: 3000, // 端口号
open: true, // 自动打开默认浏览器
compress: true, // 开启gzip压缩
hot: true
}
html文件不需要做HMR功能,因为只有一个。只需在entry里加入
entry: ['./src/index.js', './src/index.html']
js文件(非入口文件)需要修改js代码
if (module.hot) {
module.hot.accept(./xxx.js, function(){
执行回调函数
})
}
十五、 精确找到代码错误(source-map)
只需配置devtool: 'source-map'
开发环境:推荐使用evel-source-map 或者evel-cheap-moudle-source-map
生产环境:推荐使用source-map 或者 cheap-moudle-source-map
生产环境如需影藏源代码 hidden-source-map
十六、oneOf提升生产环境构建速度
注意:不能两个配置处理统一类型文件
module: {
rules: [
// 在package.json中eslintConfig --> airbnb
{
test: /\.js$/,
exclude: /node_modules/,
// 优先执行
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true
}
},
// 以下loader只会匹配一个
oneOf: [
{
test: /\.css$/,
use:[...commonCssLoader]
},
{
test: /\.less$/,
use:[
...commonCssLoader,
'less-loader'
]
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// 按需处理js
presets: [
[
'@babel/preset-env',
{
useBuildIns: usage, // 表示按需加载
coreJs: {
version: 3 // corejs版本
},
// 兼容到那个指定浏览器版本
targets: {
chrme: '60',
ie: '9',
firefox: '60',
edge: '17',
safari: '10'
}
}
]
]
}
},
{
test: /\.(jpg|png|gif)$/,
loder: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
esmodule: false,
outputPath: 'imgs'
}
},
{
test: /\.html$/,
loder: 'html-loader'
},
{
exclude: /\.(html|js|css|less|jpg|png|gif)$/,
loder: 'file-loader',
options: {
name: '[hash:10].[ext]',
outputPath: 'others'
}
}
]
]
}
十七、优化生产环境缓存
开启babel缓存
{
test: /\.js$/,
exclude: /node_modules/,
// 优先执行
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true
},
// 第二次构建时,读取缓存
cacheDirectory: true
}
开启文件资源缓存,需要在服务端代码改动,资源文件名也需要加hash值
以nodejs为例:
app.use(express.static('bulid', {maxAge: 1000 * 3600}))
问题:js和css共用了同一个hash值,这样就会其他文件缓存失效
解决:资源文件名添加contentHash值
十八、tree shaking去除无用代码(减少代码体积)
使用前提:使用ES6模块化,为生产环境(有可能会删除css等其他文件,需要在package.json配置)
十九、代码分割打包
1、多入口引入文件(该文件无需引入)
entry: ['./src/index.js', './src/test.js']
output: {
filename: 'js[name].[conmtenthash].[10].js', // 输出的模块模就不一样
path: resolve(__dirname, 'build')
}
2、如果引入了公共的js文件(多入口)
// 将node_module里面的文件单独打包为一个bundle
optimization: {
splitChunks: {
chunks: 'all'
}
}
3.通过js代码单独打包某一个js文件,import动态导入语法
import(/*webpackChunkName: 'test'*/./test.js).then(res => {
}).catch(err =>{
})
二十、PWA
二十一、多进程打包