webpack基本配置
vue-cli create-react-app
只需要简单地配置就可以使用jsx和typescript等一些前端新语法
配置webpack.config.js文件
- entry(项目入口)
字符串,如entry:"./src/index.js"
数组形式: 如entry:[react, react-dom],可以把数组中的多个文件打包转换为一个chunk
对象形式,如果需要配置的是多页的应用,或者抽离出指定模块作为指定公共代码,需要采用这种形式,属性名是占位符[name]的值
entry: {
main:'./src/index2.js',
second: './src/index2.js',
vendor:['react', 'react-dom']
}
- output(出口文件)
会告诉webpack在哪里输出所创建的bundle.js以及如何命名
out:{
path:path.join(__dirname, './dist'),
name: 'js/bundle-[name]-[hash].js,
chunkFilename: 'js/[name].chunk.js',
publicPath:'/dist/'
}
- module(模块的处理)
webpack只能处理js文件,所以要对传入的模块做一些预处理,用webpack的“loader”’去识别新的用法
loader的作用和基本用法
webpack中,loader的配置主要在module.rules中进行,这是一个数组,每一个rule做了两件事
识别文件类型,来确定具体处理该数据的loader(Rule.test属性)
使用相关的loader对文件进行相关的操作转换(Rule.use属性)
比如我们想要处理react中的jsx语法
module: {
rules:[{
test: /(\.jsx|\.js)/, //表示匹配规则,是一个正则表达式
use:{ //表示针对匹配文件将使用处理的loader
loader: "babel-loader",
options: {
presets: ["es2015", "react"]
}
}
}]
}
常用的loade
module.rules识别各种新语法
转换编译:script-loader, babel-loader,ts-loader,coffee-loader
处理样式:style-loader,css-loader,less-loader,sass-loader,postcss-loader
处理文件:raw--loader,url-loader,file-loader
处理数据:csv-loader,xml-loader
处理模板语言:html-loader,pug-loader,jade-loader,markdown-loader
清理和测试:mocha-loader,eslint-loader
- plugin(loader不能做的处理都能交给plugin来做)
const CleanWebpackPlugin = require("clean-webpack-plugin")
{
...
plugin:[
new webpack.DefinePlugin({
"process.env" : {
NODE_ENV: JSON.stringify("production")
}
}),
new CleanWebpackPlugin(["js"], {
root: __dirname + "/stu/",
verbose: true,
dry: false
})
]
}
常见的plugins:
const HtmlWebpackPlugin = require('html-webpack-plugin')
HtmlWebpackPlugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
CleanWebpackPlugin
一些辅助开发的相关属性
devtool:打包后的代码和原始代码存在较大的差异,此选项控制是否生成以及如何生成sourcemap
devserver:通过配置devserver选项,可以开启一个本地服务器
watch:启用watch模式后,webpack将持续监听热河已经解析文件的更改,开发是开启会很方便
watchoption:用来定制watch模式的选项
performance:打包后命令行如何展示性能提示,如果超过某个大小是警告还是报错
- 对于webpack配置,要区分开发环境还是产环境
为了避免重复应该提取公共代码
-所以一般有这么几个文件
webpack.config.js
webpacl.dev.js
webpack.prod.js
webpack.common.js
1、webpack.base.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'index.js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
'useBuiltIns': 'entry'
}]
],
plugins: ['@babel/plugin-transform-runtime']
}
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new CopyWebpackPlugin([{
from: 'static',
to: 'static'
}, ])
],
stats: {
children: false
}
}
2、webpack.config.js
const merge = require('webpack-merge')
const baseConfig = require('./webpack.base.config')
const devConfig = require('./webpack.dev.config')
const proConfig = require('./webpack.pro.config')
module.exports = (env, argv) => {
let config = argv.mode === 'development' ? devConfig : proConfig;
return merge(baseConfig, config);
};
3、webpack.dev.config.js
module.exports = {
devtool: 'cheap-module-eval-source-map'
}
4、webpack.pro.config.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
plugins: [
new CleanWebpackPlugin()
]
}
基本配置
拆分配置和merge
处理样式
启动本地服务
处理图片
处理ES6
模块化
- 拆分配置和merge
webpack-merge,用于将配置文件进行合并
npm install webpack-merge
配置(手动指定config)
package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config ./build/prod.config.js",
"dev": "webpack-dev-server --open --config ./build/dev.config.js"
},
- 处理样式
样式预处理,指的是在开发中使用到的一些预编译语言,如SCSS. LESS等,在项目打包过程中再将这些预编译语言转换为CSS
在module.rules
{
test: /\.css$/,
// loader 的执行顺序是:从后往前
use: ['style-loader', 'css-loader', 'postcss-loader'] // 加了 postcss
},{
test: /\.less$/,
// 增加 'less-loader' ,注意顺序
use: ['style-loader', 'css-loader', 'less-loader']
}
- 启动本地服务
安装
npm install --save-dev webpack-dev-server
运行
npx webpack-dev-server
devServer: {
port: 8080,
progress: true, // 显示打包的进度条
contentBase: distPath, // 根目录
open: true, // 自动打开浏览器
compress: true, // 启动 gzip 压缩
// 设置代理
proxy: {
// 将本地 /api/xxx 代理到 localhost:3000/api/xxx
'/api': 'http://localhost:3000',
// 将本地 /api2/xxx 代理到 localhost:3000/xxx
'/api2': {
target: 'http://localhost:3000',
pathRewrite: {
'/api2': ''
}
}
}
}
为了方便,我们通常会在package.json文件中写入一项命令配置本地服务启动。
"scripts": {
"dev": "webpack-dev-server",
}
通过命令npm run dev就可以挂载我们指定的目录,从而启动本地服务了。
- 处理图片
安装依赖
npm i -D file-loader
在module.rules
{
test: /\.(png|svg|jpg|gif)$/,
use: {
loader: 'file-loader',
options: {
name:'assets/[name].[ext]',
}
}
},
- 处理ES6
使用babel处理es6语法
安装
npm install –save-dev babel-loader @babel/core
webpack.cofig.js配置
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules,
//node_modules的js文件不用ES6转化为ES5
loader: "babel-loader"
}
]
}
webpack配置多入口
const path = require('path');
module.exports={
//入口文件的配置项
entry:{
entry:'./src/entry.js',
//这里我们又引入了一个入口文件
entry2:'./src/entry2.js'
},
//出口文件的配置项
output:{
//输出的路径,用了Node语法
path:path.resolve(__dirname,'dist'),
//输出的文件名称
filename:'[name].js'
},
//模块:例如解读CSS,图片如何转换,压缩
module:{},
//插件,用于生产模版和各项功能
plugins:[],
//配置webpack开发服务功能
devServer:{}
}
webpack抽离压缩css文件
需要安装以下插件
mini-css-extract-plugin //把css抽离成单独的文件
optimize-css-assets-webpack-plugin //把抽离出来的css代码压缩
terser-webpack-plugin //压缩js代码
uglifyjs-webpack-plugin作用: 压缩is代码,不支持压缩es6
terser-webpack-plugin作用:压缩is代码,支持压缩es6
需要安装的loader
MiniCssExtractPlugin.loader 把css抽离成单独的文件
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
const Webpackbar = require('webpackbar');
module.exports = {
// production模式自动压缩html,js,css,不用额外使用terser-webpack-plugin来压缩js
// 但是如果要分离css,不管是dev还是prod都需要使用mini-css-extract-plugin
// 但是如果要压缩分离出来的css,不管是dev还是prod都需要使用optimize-css-assets-webpack-plugin
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
filename: '[name]_[hash:8].js',
path: path.resolve(__dirname,'../build'),
publicPath: './'
},
plugins:[
// 打包之后自动生成index.html文件
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/index.html'
}),
// 打包之前自动删上一次的打包结果
new CleanWebpackPlugin(),
// 打包时候的进度条
new Webpackbar({color: 'purple'}),
// 抽离css
new MiniCssExtractPlugin({
filename: "css/[name]_[hash:8].css",
chunkFilename: "[id].css"
}),
// 压缩css
new OptimizeCssAssetsPlugin(),
// 压缩js
new TerserJSPlugin(),
],
module: {
rules:[
{
test:/\.css$/,
use: [
// 这里一定要使用MiniCssExtractPlugin.loader才能达到抽离css的效果
{
loader: MiniCssExtractPlugin.loader,
},
'css-loader',
'postcss-loader',
'less-loader'
]
}
]
}
}
webpac抽离公共代码和第三方代码
CDN内容分发网络
项目中分别有a.js, b.js, page1.js, page2.js这四个JS文件, page1.js 和 page2.js中同时都引用了a.js, b.js, 这时候想把a.js, b.js抽离出来合并成一个公共的js,然后在page1, page2中自动引入这个公共的js,怎么配置如下:
optimization(优化),与module,output(出口),plugins(插件)同级
optimization下面minimizer是压缩css,splitChunks的common配置
optimization下面vendor配置抽离第三方代码
module.exports = {
//...
//优化项配置
optimization: {
// 分割代码块
splitChunks: {
cacheGroups: {
//公用模块抽离
common: {
chunks: 'initial',
minSize: 0, //大于0个字节
minChunks: 2, //在分割之前,这个代码块最小应该被引用的次数
},
//第三方库抽离
vendor: {
priority: 1, //权重
test: /node_modules/,
chunks: 'initial',
minSize: 0, //大于0个字节
minChunks: 2, //在分割之前,这个代码块最小应该被引用的次数
}
}
}
}
}
webpack实现异步加载JS
module chunk bundle 的区别
module -各个源码文件,webapck中一切皆模块
chunk -多个模块组件的,如entry import() splitChunk
bundle最终的输出文件
webpack优化构建速度
优化babel-loder
InnorePlugin
noParse
happyPack
ParallelUglifyPlugin
自动刷新
happyPack
- happyPack多线程打包
- JS单线程,开启多线程打包
- 提高构建速度,特别是多核CPU
- ParallelUglifyPlugin多进程压缩JS
- webapck内置Uglify工具压缩js
- js单线程,开启多进程压缩更快
- 和happyPack同理
- 关于开启多进程
项目较大,打包较慢,开启多进程能提高速度
项目较小,开启多进程会降低速度(进程开销)
按需使用
webpack配置热更新
自动刷新
watchOptions: {
ignored: /node_modules/, // 忽略哪些
// 监听到变化发生后会等300ms再去执行动作,防止文件更新太快导致重新编译频率太高
// 默认为 300ms
aggregateTimeout: 300,
// 判断文件是否发生变化是通过不停的去询问系统指定文件有没有变化实现的
// 默认每隔1000毫秒询问一次
poll: 1000
}
- 热更新
自动刷新:整个网页全部刷新,速度较慢
自动刷新:整个网页全部刷新,状态会丢失
热更新:新代码生效,网页不刷新,状态不丢失
const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin');
plugins: [
new webpack.DefinePlugin({
// window.ENV = 'production'
ENV: JSON.stringify('development')
}),
new HotModuleReplacementPlugin()
],
devServer: {
port: 8080,
progress: true, // 显示打包的进度条
contentBase: distPath, // 根目录
open: true, // 自动打开浏览器
compress: true, // 启动 gzip 压缩
hot: true,
// 设置代理
proxy: {
// 将本地 /api/xxx 代理到 localhost:3000/api/xxx
'/api': 'http://localhost:3000',
// 将本地 /api2/xxx 代理到 localhost:3000/xxx
'/api2': {
target: 'http://localhost:3000',
pathRewrite: {
'/api2': ''
}
}
}
},
何时使用DllPlugin
前端框架如Vue React,体积大,构建慢
较稳定,不常升级版本
同一个版本只构建一次即可,不用每次都重新构建
webpack已内置DllPlugin支持
DllPlugin-打包出dll文件
DllReferencePlugin
webpack优化构建速度
webpack优化构建速度(可用于生产环境)
优化babel-loader
IgnorePlugin
noParse
happyPack
ParellelUqlifyPlugin
webpack优化构建速度(不用于生产环境)
自动刷新
热更新
DllPlugin
webpack性能优化-产出代码
体积更小
合理分包,不重复加载
速度更快,内存使用更少
{
test: /\.(png|jpg|jpeg|gif)$/,
use: {
loader: 'url-loader',
options: {
// 小于 5kb 的图片用 base64 格式产出
// 否则,依然延用 file-loader 的形式,产出 url 格式
limit: 5 * 1024,
// 打包到 img 目录下
outputPath: '/img1/',
// 设置图片的 cdn 地址(也可以统一在外面的 output 中设置,那将作用于所有静态资源)
// publicPath: 'http://cdn.abc.com'
}
}
},
webapck性能优化-产出代码
小图片base64 编码
bundle加hash
懒加载
使用prodction
Scope Hosting
提取公共代码
IngorePlugin
使用CDN加速
Tree-Shaking
自动开启代码压缩
Vue React等会自动删掉调试代码,(如开发环境的warning)
启动Tree-Shaking