一、webpack五大核心概念
1、entry
打包的入口,可以是字符串、数组或对象
2、output
打包的输出
3、mode
模式,可以分为开发模式(development)与生产模式(production),默认为生产模式
4、loader
默认只能处理js、json格式的文件,loader的作用就是将其他格式的文件,转换成webpack能够处理的文件
5、plugin
webpack插件,每一个插件都有一个特定的功能,能处理loader无法处理的事情
二、HtmlWebpackPlugin与CleanWebpackPlugin
- HtmlWebpackPlugin:生成一个html文件,自动打包后的js文件
- CleanWebpackPlugin:每次打包时自动清除旧的文件,默认清除output.path目录
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.export = {
entry: {
page1: './src/page1.js',
page2: './src/page2.js',
common: './src/common.js',
},
output: {
path: './dist',
filename: '[chunkhash].js'
},
plugin: [
new HtmlWebpackPlugin({
filename: 'index.html', // 生成html的文件名
template: './src/template.html', // 指定模版
title: 'this is title', // 设置html的title,可在指定模版中通过ejs语法引入
inject: true, // 默认值,script标签位于body底部,可选值为body、header、false(表示不自动引入)
hash: false, // true表示引入js文件后面添加hash值作为参数
chunks:L [page1, common], // 多入口打包会有多个文件,默认引入全部,此配置表示只引入page1,common
minify: {
collapseWhitespace: true, // 去除空格
minifyCSS: true, // 压缩html内联的css
minifyJS: true, // 压缩html内联的js
removeComments: true // 移除注释
}
}),
new CleanWebpackPlugin(),
]
}
三、处理项目中的样式文件
webpack默认无法处理css、less、scss等文件,需要借助插件来处理项目中的样式文件
- npm i css-loader mini-css-extract-plugin sass-loader node-sass -D
- npm i optimize-css-assets-webpack-plugin -D
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
module.export = {
...
module: {
rules: [
{
test: /\.(css|scss)$/,
use: [
MiniCssExtractPlugin,
'css-loader',
'sass-loader',
]
}
]
},
plugins: [
// 将css单独插入html中
new MiniCssExtractPlugin(),
// 压缩css大小
new OptimizeCssAssetsPlugin,
// 每次打包先清除dist文件夹
new CleanWebpackPlugin(),
new HtmlWebpackPlugin()
]
}
四、处理项目中的图片
npm i file-loader html-loader url-loader image-webpack-loader -D
- file-loader 处理图片
- html-loader 处理html中src引入的图片
- url-loader 将图片转为base64,压缩图片体积
- image-webpack-loader,压缩图片体积,不能与url-loader一起使用
module.exports = {
...
output: {
publicPath: './'
},
plugins: [
new MiniCssExtractPlugin({
filename: 'style/[name].css'
})
]
module: {
rules: [
{
test: /\.(scss|css)$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
},
},
'css-loader',
'sass-loader',
],
},
{
test: /\.(png|jpeg|gif|svg|jpg)/,
use: {
loader: 'url-loader',
options: {
name: '[name]-[contenthash:10].[ext]', // ext表示文件的后缀名
esModule: false, // 不使用es6的模块化语法
outputPath: 'images',
limit: 10 * 1024, // 表示小于10kb的图片会被base64编码
},
},
},
{
test: '/\.html$/',
use: 'html-loader',
},
],
},
}
五、理解name、hash、chunkhash、contenthash
- name:chunk name,chunk的名称,多入口chunkname为其key值,单入口不指定默认为main,异步加载的模块默认为数字
- hash:每次打包生成的hash,项目中任意与打包相关的文件内容改变,此hash就会改变
- chunkhash:根据chunk的内容生成的hash
- contenthash:单个输出文件内容的hash
六、devServer的使用
webpack-dev-server是webpack官方提供的一个小型express服务器,它可以为webpack打包生成的资源文件提供web服务
首先安装:npm i webpack-dev-server -D
在package.json中配置
"script": {
...
"start": "webpack-dev-server"
}
// webpack.config.js
module.exports = {
...
devServer: {
contentBase: path.resolve(__dirname, 'public'), // 告诉服务器从哪里提供内容,默认为当前工作目录
watchContentBase: true, // 监视contentBase里面的内容,一旦变化就reload
watchOptions: {
ignore: '' // 忽略哪些文件的变化
},
historyApiFallback: true, // 请求的资源不存在时返回index.html,比如vue-router的history模式
clientLogLevel: 'none', // 不要显示启动日志信息
overlay: false, // 如果出错,不要全屏提示
progress: true, // 控制台输出运行进度
compress: true, // 启用gzip压缩
open: true, // 自动打开浏览器
host: '0.0.0.0', // 如果希望被局域网访问,设置为0.0.0.0,默认为localhost
port: '8888', // 端口,默认8080
useLocalIp: true, // 使用本地ip,如果host设置0.0.0.0,这里需要设置为true
hot: true, // 开启热更新
proxy: { // 设置代理
'api': { // 当url中含有/api时就会使用这里设置的代理
target: 'http://xxx.com', // 目标服务器地址
changeOrigin: true, // 跨域
ws: true, // 代理websocket
pathRewrite: {
'^/api': '' // url重写,将url里面的/api去掉
}
}
}
}
}
七、js兼容性处理
由于ie浏览器无法识别高阶语法,因此需要使用babel来转换这些语法
- babel-loader
- @babel/core (babel核心库、核心api)
- @babel/preset-env (babel预设,babel是插件化的,转换不同的语法,需要不同的插件,预设的作用就是按需引入)
npm i babel-loader @babel/core @babel/preset-env -D
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/, // 不处理node_modules中的文件
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
}
还要安装@babel/polyfill来处理ES6中的一些语法
@babel/polyfill 其实是 core-js2 与 regenerator-runtime 组成的一个集成包,使用 core-js2,则安装 @babel/polyfill,使用 core-js3 则安装 core-js 与 regenerator-runtime ,以 core-js3 为例
npm i core-js regenerator-runtime -S
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/, // 不处理node_modules中的文件
use: [
{
loader: 'babel-loader',
options: {
presets: [
['@bebel/preset-env', {
modules: false, // 对ES6模块文件不做转化,以便使用 tree shaking
useBuiltIns: usage, // 取值可以是false,'entry','usage'
corejs: 3, // corejs版本号
targets: {} // 需要兼容的浏览器,未配置,取 browserslist中的值
}]
]
}
}
]
}
]
}
}
关于useBuiltIns取值的说明
- false:需要在js文件顶部引入,不需要指定corejs版本号
// <--- core-js2 --->
// import "@babel/polyfill";
// <--- core-js3 --->
import "core-js/stable";
import "regenerator-runtime/runtime";
- entry:需要在js文件顶部引入,需要指定corejs版本号,根据配置的浏览器,打包浏览器不兼容的内容
- usage:不需要在js文件顶部引入,需要指定corejs版本号,根据配置的浏览器,以及代码中用到的API来按需打包
当项目中的js越来越多,babel转换耗时越来越长,可以使用babel缓存及多进程打包来提高速度,安装thred-loader
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/, // 不处理node_modules中的文件
use: [
{
loader: 'thred-loader', // 耗时比较长的 loader 才需要多进程,否则只会更慢
options: {
workers: 2 // 进程数
}
},
{
loader: 'babel-loader',
options: {
presets: [
['@bebel/preset-env', {
modules: false, // 对ES6模块文件不做转化,以便使用 tree shaking
useBuiltIns: usage, // 取值可以是false,'entry','usage'
corejs: 3, // corejs版本号
targets: {} // 需要兼容的浏览器,未配置,取 browserslist中的值
}]
]
}
}
]
}
]
}
}
八、其他配置
1、resolve:设置模块如何被解析
alias:为路径设置别名,让引入变得更简单
// webpack.config.js
module.exports = {
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
// $ 匹配结尾,不会影响vue/xxx的路径,表示项目中引入的vue为运行时版本
'vue$': 'vue/dist/vue.runtime.js'
}
}
}
extensions: 引入哪些类型的文件时可以省略后缀名
resolve: {
// 默认为['.js', '.json'],表示引入js、json、vue文件时不需要写后缀名
extensions: ['.js', '.json', '.vue']
}
2、externals:设置某些库不被打包,从外部获取
// index.html 中 body 底部添加
<body>
<% for (let src of htmlWebpackPlugin.options.cdnList) { %>
<script src="<%= src %>"></script>
<% } %>
<!-- 直接写死,与上面二选一,推荐上面的方式 -->
<script src="https://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
</body>
// webpack.config.js 添加下面内容
module.exports = {
externals: {
jquery: "jQuery" // key 为引入的包名,value 为全局变量名
},
plugins: [
new HtmlWebpackPlugin({
// 用来在 html 中通过 script 引入,cdnList 为自定义变量。若直接写死则不需要此配置
cdnList: ["https://libs.baidu.com/jquery/2.0.0/jquery.min.js"]
})
]
}
3、watch:初始构建之后,继续监听任何已解析文件的更改
将此参数设置为 true,使用 webpack 打包之后,每当有文件内容发生变化,就会自动重新打包(devServer默认开启)
module.exports = {
watch: true,
watchOptions: {
aggregateTimeout: 300, // 延时 300ms 打包,防抖
ignored: /node_modules/, // 忽略监听,也可以是 anymatch 模式,例: "files/**/*.js"
poll: true // 开启轮询模式,如果值为数字,表示轮询的间隔,单位毫秒
}
}