目录
webpack默认特性
- webpack默认能处理js/json文件,不能处理css,img等其他资源
- 生产环境会比开发环境 多一个压缩js代码
webpack.config.js
const webpack = require('webpack');
const { resolve } =require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
// contenthash 根据内容生成的hash值
// hash 每次webpack都会生成唯一hash值(js和css的hash一样,重新打包会导致所有缓存失效)
// chunkhash 根据chunk生成hash值(同chunk的hash一样。css通过js引入,chunk一样,修改js,css也会缓存失效)
module.exports = {
entry: resolve(__dirname,"main.js"),//入口文件
// entry: {main: 'app/main.js', test: 'app/test.js'} 多入口文件
output: {
path: resolve(__dirname,"/dist"),//打包后的文件存放的地方
filename: "[name].[contenthash:10].js"//打包后输出文件的文件名
},
devtool: 'eval-source-map', // 调试压缩之后的log显示具体行数 'eval-source-map'模式中小型项目的首选,但是具有安全隐患,最好只在开发时使用
mode: 'development', // production 生产环境会自动压缩js代码,无需我们关系
// 也可以直接将devServer配置在package,json/scripts 启动命令中
devServer: { //开发服务器的配置
port: 3000,//自定义访问的端口号
open: true,
hot: true,
compress: true, //启动gzip压缩,启动速度快
progress: true,
contentBase: resolve(__dirname, 'dist') //运行的文件目录
},
resolve: {
//配置别名,在项目中可缩减引用路径,在项目可以直接使用@代替后面复杂的代码
alias: {
'@': '/src'
}
},
module: {
rules: [
{
test: /\.less$/,
exclude: /node_modules/,
use: [ // use的loader执行顺序后=>前
// 创建style标签,将js中的样式资源插入,添加到head中
// 'style-loader',
// 取代style-loader,提取js文件中css压缩打包成单独文件
MiniCssExtractPlugin.loader,
// 将css文件变成commonjs模块加在js中,里面样式是字符串
'css-loader',
// 将less处理成css
'less-loader',
]
},
{
test: /\.(jpg|png|gif)$/,
exclude: /node_modules/,
// 处理图片, 下载url-loader需要下载file-loader。依赖关系
// 默认无法处理html中引用的图片
loader: 'url-loader',
options: {
// 图片小于设置的8kb,会被处理成base64
limit: 8 * 1024,
// 如果html-loadefr处理过的图片会是commonjs.
//而url-loader是es6模块化,html-loader处理之后src="[object,module]" 会报错。需要关闭es6模块化解析
esModule: false,
// 自定义图片名称,[hash:10]取hash值前10位。[ext]取原扩展名
name: '[hash:10].[ext]',
outputPath: 'imgs' // 输出路径
}
},
{
test: /\.html$/,
// 处理html中的img的引入,从而可以让url-loader进行打包处理
loader: 'html-loader',
},
{ // 打包其他资源(字体图标之类),除了(html,js,css资源以外的资源)
exclude: /\.(js|less|html)$/,
loader: 'file-loader',
options: {
outputPath: 'otherMedias'
}
},
// {
// // 语法检查, 如果对loader有配置,则用下面写法options
// // 设置检查规则, package.json中eslintConfig中设置。"eslintConfig": {"extends":"airbub-base"}
// // 使用airbnb规则 需要依赖 eslint-config-airbub-base eslint eslint-plugin-import
// test: /\.js$/,
// exclude: /node_modules/,
// enfore: 'pre', //优先执行,不然会和babel-loader冲突
// loader: 'eslint-loader',
// options: {
// // 自动修复eslint错误
// fix: true
// }
// },
{
// js基础转译处理需要安装babel-loader @babel/preset-env @babel/core (转换箭头函数等一些基础语法)
// js全部兼容转译 页面引入 import @babel/polyfill (promise之类的复杂语法都可以)(体积过大)
// 或者引入core-js进行按需解决兼容
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: "thread-loader", // 开启多进程打包
options: {
workers: 2 // 2个进程
}
},
{
loader: "babel-loader",
options: {
presets: [
'@babel/preset-env',
// // 引入core-js的方案配置
// {
// // 按需加载,指定版本
// useBuiltIns: 'usage',
// corejs: {
// version: 3
// },
// // 指定兼容到哪个版本浏览器
// targets: {
// chrome: '60',
// firefox: '60',
// ie: '10',
// safari: '10',
// edge: '17'
// }
// }
]
}
}
],
}
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(), //启用HMR,配合server的hot
new MiniCssExtractPlugin({
//对输出文件重命名
filename: 'css/build.[contenthash:10].css'
}),
// 压缩css代码
new OptimizeCssAssetsPlugin(),
new HtmlWebpackPlugin({
template: resolve(__dirname, 'index.html'),
// 压缩html
minify: {
collapseWhitespace: true, //移除空格
removeComments: true // 移除注释
}
}),
//提供全局的变量,在模块中使用无需用import和require引入
new webpack.ProvidePlugin({
$: 'jquery', // cnpm i jquery --save 需要提前装包
}),
],
// 可以将node_modules中代码单独打包一个chunk单独输出。也可以将代码中import(/* webpackChunkName: 'test' */'./xx.js).then(() => { todo }) xx.js资源进行单独输出
// 预加载 import(/* webpackChunkName: 'test', webpackPrefetch: true */'./xx.js).then(() => { todo })
optimization: { //独立分包
splitChunks: {
chunks:'all'
}
},
externals: { // 不需要打包哪些资源
// 库名: npm包名
jquery: 'jQuery'
}
}
整体的简介
- entry是入口文件 (__dirname”是node.js中的一个全局变量,它指向当前执行脚本所在的目录)
- output是出口文件
- devtool是调试log显示
- devServer (搭建服务器, 可以热刷新, 反向代理)
modules
(通过使用不同的loader
,webpack
有能力调用外部的脚本或工具,实现对不同格式的文件的处理)Plugins (插件, 是用来扩展webpack功能的)
Loaders配置
Loaders需要单独安装并且需要在
webpack.config.js
中的modules
关键字下进行配置,Loaders的配置包括以下几方面:cnpm install style-loader css-loader less-loader
test
:一个用以匹配loaders所处理文件的拓展名的正则表达式(必须)loader
:loader的名称(必须)include/exclude
:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);options
:为loaders提供额外的设置选项(可选)
Babel的配置
可以在webpack.config中进行配置, 但是babel也会有很多配置,就抽出去进行编辑, 放在.bablerc文件中配置。(webpack会自动调用
.babelrc
里的babel配置选项)cnpm install babel-core babel-loader babel-pkugin-transform-runtime 第一套包 转换插件
cnpm install babel-preset-env babel-preset-stage-0 第二套包 语法插件(babel-preset-env语法比较新,包括es***任何版本)
根目录下建.babelrc文件
{
"presets": ['env', "stage-0"] // 语法
"plugins": ["transform-runtime"]
}
优化
UglifyJsPlugin
:压缩JS代码;ExtractTextPlugin
:分离CSS和JS文件
1.HMR功能,模块热替换,只打包本次修改的。配置devserver: hot: true
- css模块:支持hmr,因为style-loader内部做了
- html模块:默认不能使用hmr,同时会导致html文件不能热更新了(热更新解决:入口配置添加html。只有一个html页面,不需要支持hmr功能)
- js模块:默认不支持hmr。在入口js进行modult.hot监听判断,监听各个引入的子js,哪个改变,重新调用哪个。主入口js无法做HMR.
2.调试source-map。配置devtool: 'source-map' (打包会多处.map文件,是源文件的映射文件)
- devtool:'inline-source-map' (构建速度快。不会生成.map文件,会把映射代码追加到打包js文件代码后面)
3.用oneof处理loader。类型于break。问题:如果有两个loader处理一个类型文件,那只会走一个了。解决(把不是单一处理的loader提到oneof外面即可)
4.添加缓存,contenthash命名。
5. tree shaking(去除无用代码)
- 前提:必须使用es6 module, 开启mode的production模式
- 作用:减少代码
- 在package.json中配置 "sideEffects":["*.css"] // 表示除了css文件,其他都可以进行tree shaking处理。(css/@babel/polyfill,所以要把css保护起来)
6.splitChunks将文件单独打包,配置optimization:{},例子看上代码
7.懒加载,基于splitChunks分割,触发时机 按需引入实现懒加载。例子看上代码
8.预加载,基于懒加载实现,import中配置webpackPrefetch说明实现。预加载是其他资源加载之后,空闲时请求回来,只是不在页面加载,按时机加载资源。例子看上代码
9.PWA 渐进式网络开发 (离线也可访问)。
10.多进程打包, 安装thread-loader。(多进程启动约600ms,进程通信也需要时间,视情况看是否使用)
11.externals 不需要打包哪些资源(比如一些jq资源,不需要打包。可以在html上加载CDN使用)
然后手动在html中引入在线jq资源包
12.dll 建webpack.dll.js文件配置。执行命令webpack --config webpack.dll.js 打包。 对某些库进行单独打包(jquery等)。然后需要在webpack.config.js中使用dll插件来配置引用dll.js输出的包。
externals和dll区别:
- externals三方库直接不打包,走CDN.
- dll三方库单独打包出来,部署引用。