最近在学习webpack,整理一下代码
主文件webpack.config.js
// resolve用来拼接绝对路径的方法
const { resolve } = require(‘path‘);
const htmlWebpackPlugin = require(‘html-webpack-plugin‘);
const miniCssExtractPlugin = require(‘mini-css-extract-plugin‘);
const optimizeCssAssetsWebpackPlugin = require(‘optimize-css-assets-webpack-plugin‘);
const addAssetHtmlWebpackPlugin = require(‘add-asset-html-webpack-plugin‘);
const { CleanWebpackPlugin } = require(‘clean-webpack-plugin‘);
const { BundleAnalyzerPlugin } = require(‘webpack-bundle-analyzer‘);
// Happypack任务分解为多个子进程,完成后并入主线程(适合大型项目)
const HappyPack = require(‘happypack‘);
// 根据cpu数量创建线程池
const happyThreadPool = HappyPack.ThreadPool({size:OscillatorNode.cpus().length});
/*
PWA:渐进式网络开发应用程序(离线可访问)
workbox --> workbox-webpack-plugin
*/
const workBoxWebpackPlugin = require(‘workbox-webpack-plugin‘);
// 以前使用的是Ulgify,现在webpack内置terser plugin进行文件压缩优化
const TerserPlugin = require(‘terser-webpack-plugin‘);
const webpack = require(‘webpack‘);
/*
tree shaking:去除无用代码
前提:1.必须使用es6模块化 2.开启production模块
作用:减少代码体积
"sideEffects": false 所有代码都没有副作用(都可以进行tree shaking)
问题:可能会把除了js文件之外的文件也去除掉可以通过"sideEffects": ["*.css"]不进行tree shaking
*/
const commonCssLoader = [
// use数组中loader顺序:从后到前的顺序,依次执行
// 创建style标签,将js中的样式资源插入进行,添加到head中生效
// ‘style-loader‘,
// 取代style-loader 作用:提取js中的css成单独文件
miniCssExtractPlugin.loader,
// 将css文件变成commonjs模块加载到js中,里面内容是样式字符串
‘css-loader‘,
/*
css 兼容性处理:postcss --> postcss-loader postcss-preset-env
*/
// 使用loader的默认配置
// postcss-loader 修改loader的配置
{
loader: ‘postcss-loader‘,
options: {
ident: ‘postcss‘,
plugins: () => [
// postcss的插件
require(‘postcss-preset-env‘)()
]
}
}];
process.env.NODE_ENV = ‘development‘;
module.exports = {
// import导入的没有加后缀的文件,自动加上后缀
resolve: {
extensions: [‘.js‘]
},
// webpack配置
// 入口起点
entry: [‘./index.js‘, ‘./demo.html‘],
output: {
// 输出文件名
filename: ‘js/built.js‘,
// 输出路径
path: resolve(__dirname, ‘build‘)
},
// loader的配置
module: {
// 不打包的文件
noParse: /node_modules\/(echarts)/,
// 详细loader配置
rules: [
// 1.js兼容性处理:babel-loader @babel/preset-env @babel/core
// 问题:babel只能转换一些基本语法 例如:Promise就不能转换
// 2. 全部js兼容性处理 --> @babel/polyfill
// 解决了所有的兼容性问题,但是打包后的文件体积过大
// 3.需要做兼容性处理的才进行改良:按需加载 --> core.js
{
test: /\.js$/,
exclude: /node_modules/,
use: [
// 开启多进程打包
// 进程启动大概为600ms,进程通信也有开销
// 只有工作消耗时间比较长,才需要多进程打包
‘thread-loader‘,
{
loader: ‘babel-loader‘,
options: {
// 预设:指示babel做怎样的兼容性处理
presets: [
[‘@babel/preset-env‘,
{
// 按需加载
useBuiltIns: ‘usage‘,
// // 指定core-js版本
corejs: {
version: 3
},
// 指定兼容性做到哪个版本的浏览器
targets: {
chrome: ‘60‘,
firefox: ‘60‘,
ie: ‘9‘,
safari: ‘10‘,
edge: ‘17‘
}
}]
],
// 开启babel缓存
// 第二次构建,会读取之前的缓存
cacheDirectory: true,
/*
文件资源缓存
hash:每次webpack构建时会生成一个唯一的hash值。
问题:因为js和css同时使用一个hash值
如果重新打包,会导致所有缓存失效。(可能我却只改动一个文件)
chunkhash:根据chunk生成的hash值。如果打包来源于同一个chunk,那么hash值就一样
因为css是在js中被引入的,所以同属于一个chunk
contenthash:根据文件的内容生成hash值,不同文件hash值一定不一样 --> 让代码上线运行缓存更好使用
*/
}
}
]
},
// 语法检查:eslint-loader eslint
// 只检查自己写的源代码,不检查第三方库的代码
// 设置检查规则: package.json中eslintConfig中设置~
// 推荐airbnb规则 --> eslint-config-airbnb-base eslint eslint-plugin-import
{
test: /\.js$/,
exclude: /node_modules/,
loader: ‘eslint-loader‘,
enforce: ‘pre‘,
options: {
// 自动修复语法
fix: true
}
},
{
// 以下loader只会执行一个
// 如果有两个loader同时处理一种类型文件,则会出错
oneOf: [
{
test: /\.css$/,
use: [...commonCssLoader]
},
{
// 匹配哪些文件
test: /\.less$/,
// 使用哪些loader进行处理
use: [
...commonCssLoader,
‘less-loader‘
]
},
{
test: /\.(jpg|png|gif)$/,
// 需要下载两个loader,下载url-loader以及它依赖的file-loader
loader: ‘url-loader‘,
options: {
// 图片小于8kb,就会被base64处理
// 优点:减少请求数量(减轻服务器压力)
// 缺点:图片体积会更大(文件请求速度更慢)
limit: 8 * 1024,
esModule: false,
outputPath: ‘images‘,
name: ‘[hash:10].[ext]‘
}
},
{
test: /\.html$/,
// 处理html文件的img图片(负责引入img,从而能被url-loader进行处理)
loader: ‘html-loader‘
},
// 打包其他资源(除了html/js/css资源以外的资源)
{
exclude: /\.(js|css|html|less|jpg|png|gif)$/,
loader: ‘file-loader‘,
options: {
outputPath: ‘media‘,
name: ‘[hash:10].[ext]‘
}
}
]
}
]
},
// externals: {
// // 忽略库名 -- npm包名,设置之后的库不参与打包
// jquery: ‘jQuery‘
// },
// plugins的配置
plugins: [
// 详细plugins的配置
// html-webpack-plugin
// 功能:默认会创建一个空的html,自动引入打包输出的所有资源(JS/CSS)
// 需求:需要有结构的HTML文件
new htmlWebpackPlugin({
template: ‘./demo.html‘,
minify: {
// 移除空格
collapseWhitespace: true,
// 移除注释
removeComments: true
}
}),
new CleanWebpackPlugin(),
new miniCssExtractPlugin({
filename: ‘css/built.css‘
}),
// 压缩CSS
new optimizeCssAssetsWebpackPlugin(),
new workBoxWebpackPlugin.GenerateSW({
/*
1.帮助serviceworker快速启动
2.删除旧的serviceworker
生成一个serviceworker配置
*/
clientsClaim:true,
skipWaiting: true
}),
new webpack.HotModuleReplacementPlugin(),
// 告诉webpack那些库不参与打包,同时使用时的名称也得变~
new webpack.DllReferencePlugin({
manifest: resolve(__dirname, ‘dll/manifest.json‘)
}),
new BundleAnalyzerPlugin(),
new HappyPack({
id: ‘babel‘,
threads: happyThreadPool,
// happypack有很多不支持的loader,请查看官方进行使用
loaders: [‘babel-loader‘]
})
// 将某个文件打包输出去,并在html中自动引入该资源
// new addAssetHtmlWebpackPlugin({
// filepath: resolve(__dirname, ‘dll/jquery.js‘)
// })
],
// 模式
mode: ‘production‘, // 开发模式
/*
可以将node_modules中代码单独的打包一个chunk最终输出
自动分析多入口chunk中,有没有公共的文件,如果有会打包成单独一个chunk
*/
optimization: {
splitChunks: {
chunks: ‘all‘
},
minimizer: [
new TerserPlugin({
// 加快构建速度
cache: true,
// 开启多线程
// parallel: true,
terserOptions: {
// 打包时将无用代码去除
compress: {
unused: true,
drop_debugger: true,
drop_console: true,
dead_code: true
}
}
})
]
},
// 开发服务器 devServer:用来自动化(自动编译,自动打开浏览器,自动刷新浏览器...)
// 特点:只会在内存中编译打包,不会有任何输出
// 启动devServer指令为:npx webpack-dev-server
devServer: {
contentBase: resolve(__dirname, ‘build‘),
/*
HMR:hot module replacement 热模块替换/模块热替换
作用:一个模块发生变化,只会重新打包一个模块(而不是打包所有模块)
极大提升构建速度
样式文件:可以使用HMR功能,但是需要使用style-loader,style-loader内部实现了HMR
js文件:默认不能使用HMR功能 -> 需要修改js代码,添加支持HMR功能的代码
注意:HMR功能对js的处理,只能处理非入口js文件的其他文件
html文件:默认不能使用HMR功能,同时会导致问题,html文件不能热更新,解决:修改entry入口,将html文件引入
*/
hot: true,
hotOnly: true,
// 启动gzip压缩
compress: true,
// 端口号
port: 3000
},
devtool: ‘source-map‘
};
/*
source-map:一种 提供源代码到构建后代码映射 技术(如果构建后代码出错了,通过映射可以追踪源代码错误)
[inline-[hidden-[eval-][nosources-][cheap-[module-]]source-map
inline-source-map:内联(只生成一个sourceMap)
hidden-source-map:外部
eval-source-map:内联(每个文件生成一个sourceMap)
nosources-source-map:外部
cheap-source-map:外部
cheap-module-source-map: 外部
*/
/* package.json添加配置
"browerslist": {
"development": [
"last 1 chrome version", // 最近的一个版本
"last 1 firefox version",
"last 1 safari version"
],
"production": [
">0.2%", // 全球有0.2%的用户使用的浏览器(也就是兼容的浏览器很老)
"not dead", //
"not op_mini all" // 不兼容op_mini
]
},
"eslintConfig": {
"extends": "airbnb-base", // 遵从airbnb代码风格
"env": {
"browser": true, // 浏览器环境
"es6": true
}
},
"sideEffects": false // 启动tree shaking
*/
dll文件
/*
使用dll技术,对某些库(第三方库:jquery,react,vue...)进行单独打包
当你运行webpack时,默认查找webpack.config.js配置文件
需求:需要运行webpack.dll.js文件
webpack --config webpack.dll.js
*/
const { resolve } = require(‘path‘);
const webpack = require(‘webpack‘);
module.exports = {
entry: {
// 最终打包生成的[name] ==> jquery
// [‘jquery‘] --> 要打包的库是jquery
jquery: [‘jquery‘]
},
output: {
filename: ‘[name].js‘,
path: resolve(__dirname, ‘dll‘),
library: ‘[name]_[hash]‘ // 打包的库里面向外暴露出去的内容叫什么名字
},
plugins: [
// 打包生成一个 manifest.json --> 提供和jquery映射
new webpack.DllPlugin({
name: ‘[name]_[hash]‘, // 映射库的暴露的内容名称
path: resolve(__dirname, ‘dll/manifest.json‘) // 输出文件路径
})
],
mode: ‘production‘
};
原文:https://www.cnblogs.com/smallZoro/p/12722174.html