webpack 基础_优化
webpack 优化配置
开发环境性能优化
- 优化打包构建速度
- 优化代码调试
生产环境性能优化
- 优化打包构建速度
- 优化代码运行的性能
HMR
hot module replacement 热模块替换/模块热替换
作用:一个模块发生变化,只会重新打包这一个模块(而不是所有模块),提升构建速度
样式文件:
- 可以使用 HMR功能;因为 style-loader内部实现了此功能
js文件:
-
默认不能使用 HMR功能
-
解决:需要修改 js代码,添加支持 HMR功能的代码
-
注意:HMR功能对 js的处理,只能处理非入口 js文件的其它文件
import '../css/iconfont.css'; import '../css/a.css'; import '../css/b.less'; import print from './print'; const add = (x, y) => x + y; console.log(add(1, 2)); if (module.hot) { // 一旦 module.hot为 true,说明开启了 HMR功能 -> 让 HMR功能代码生效 module.hot.accept('./print.js', () => { /** * 方法会监听 print.js文件变化,一旦发生变化,其它模块不会重新打包 * 会执行后面的回调函数 */ print(); }); }
html文件:
- 默认不能使用 HMR功能,同时会导致问题,HTML文件不能热更新了(程序中只有一个 HTML文件,不需要做 HMR功能)
- 解决:修改 entry入口,将 HTML文件引入
编码:
- 修改配置文件:在 devServer中添加属性 hot: true
// nodejs
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 将 css从 js中提取出来,并到单独的文件中
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// css代码压缩
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// 定义 nodejs环境变量:决定使用 browserslist的哪个环境
// process.env.NODE_ENV = 'production'
// process.env.NODE_ENV = 'development'
// loader复用
const commonCSSLoader = [
'style-loader',
// 将 css代码提取到一个指定的文件中
// MiniCssExtractPlugin.loader,
// 将 css加载到 js中
'css-loader',
/**
* css兼容性处理:只能针对 css代码来操作
* postcss ->
* postcss-loader ->
* postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
*/
{
/**
* 需要在 package.json中定义 browserslist里面的配置
*/
loader: 'postcss-loader',
options: {
// 告诉它要做哪些兼容性配置
ident: 'postcss',
plugins: () => [
/**
* postcss的插件
* 帮助 postcss找到 package.json中 browserslist里面的配置,
* 通过配置加载指定的 css兼容性样式
*/
require('postcss-preset-env')(),
],
},
},
];
// commonjs
module.exports = {
entry: ['./src/js/index.js', './src/index.html'],
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
// css代码处理
{
test: /\.css$/,
use: [
...commonCSSLoader,
// // 将 css代码提取到一个指定的文件中
// MiniCssExtractPlugin.loader,
// // 将 css加载到 js中
// 'css-loader',
// /**
// * css兼容性处理:只能针对 css代码来操作
// * postcss ->
// * postcss-loader ->
// * postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
// */
// {
// /**
// * 需要在 package.json中定义 browserslist里面的配置
// */
// loader: 'postcss-loader',
// options: {
// // 告诉它要做哪些兼容性配置
// ident: 'postcss',
// plugins: () => [
// /**
// * postcss的插件
// * 帮助 postcss找到 package.json中 browserslist里面的配置,
// * 通过配置加载指定的 css兼容性样式
// */
// require('postcss-preset-env')()
// ]
// }
// }
],
},
{
test: /\.less$/,
use: [
...commonCSSLoader,
// MiniCssExtractPlugin.loader,
// 'css-loader',
'less-loader',
],
},
/**
* 正常来讲,一个文件只能被一个 loader处理;
* 当一个文件要被多个 loader处理,那一定要指定 loader执行的先后顺序
* 如下面的 .js文件:应该先执行 eslint再执行 bable,通过 enforce属性指定
*/
// js语法检查:规范项目代码,检查常见语法错误
{
/**
* 只检查源代码,忽略第三发库
* eslint-loader
* eslint
* 在 package.json的 eslintConfig中设置检查规则,推荐 airbnb
*/
test: /\.js$/,
exclude: /node_modules/,
// 优先执行此 loader
enforce: 'pre',
loader: 'eslint-loader',
options: {
// 自动修复 eslint错误
fix: true,
},
},
{
// js兼容性处理:babel-loader、@babel/preset-env、@babel/core
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// 预设:指示 babel做怎样的兼容处理
presets: [
[
// 只能作简单的语法兼容处理
'@babel/preset-env',
// corejs可以作复杂的语法兼容处理
{
// 按需加载
useBuiltIns: 'usage',
// 指定 core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪个版本的浏览器
targets: {
chrome: '60',
firefox: '50',
safari: '10',
edge: '17',
ie: '9',
},
},
],
],
},
},
// 处理图片资源
{
test: /\.(png|gif|jpg|jpeg)$/,
loader: 'url-loader',
options: {
// 对于图片小于 8-12kb的可以进行 base64处理
limit: 8 * 1024,
// 关闭 ES6解析,使用 commonjs解析
esModule: false,
name: '[hash:10].[ext]',
outputPath: 'imgs',
},
},
// 处理 HTML中的 img资源
{
test: /\.html$/,
// 处理 HTML中的 img资源
loader: 'html-loader',
},
// 处理其它资源
{
exclude: /\.(html|js|css|less|png|gif|jpg|jpeg)/,
// 将其它资源原封不动的输出
loader: 'file-loader',
options: {
name: '[hash:10].[ext]',
outputPath: 'media',
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
// html代码压缩
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
new MiniCssExtractPlugin({
// 对提取出的 css代码放到统一的文件中,并命名
filename: 'css/built.css',
}),
// css代码压缩
new OptimizeCssAssetsWebpackPlugin(),
],
// mode: 'production',
mode: 'development',
devServer: {
contentBase: resolve(__dirname, 'build'),
compress: true,
port: 3030,
open: true,
// 开启 HRM功能
hot: true,
},
};
- 运行指令: webpack
source-map
一种提供源代码到构建后代码映射的技术,非常利于调试代码;例如构建后代码出错,通过映射关系可以追踪源代码的错误
开发环境:速度更快,调试更友好
速度快(eval > inline > cheap > ...)
- eval-cheap-source-map
- eval-source-map
调试更友好
- source-map
- cheap-module-source-map
- cheap-source-map
总结:使用 eval-source-map(调试更好)、eval-cheap-module-source-map(性能更好)
生产环境:源代码要不要隐藏,调试要不要更友好
内联会让代码体积更大,所以在生产环境不用内联
隐藏源代码
- nosource-source-map:全部隐藏
- hidden-source-map:只隐藏源代码
调试友好
- source-map
- cheap-module-source-map
总结:使用 source-map、cheap-module-source-map
- 修改配置文件:devtool: 'source-map'
// nodejs
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 将 css从 js中提取出来,并到单独的文件中
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// css代码压缩
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// 定义 nodejs环境变量:决定使用 browserslist的哪个环境
// process.env.NODE_ENV = 'production'
// process.env.NODE_ENV = 'development'
// loader复用
const commonCSSLoader = [
'style-loader',
// 将 css代码提取到一个指定的文件中
// MiniCssExtractPlugin.loader,
/**
* 问题:
* MiniCssExtractPlugin.loader当前不能将 less文件单独提取出来放到指定的文件中
*/
// 将 css加载到 js中
'css-loader',
/**
* css兼容性处理:只能针对 css代码来操作
* postcss ->
* postcss-loader ->
* postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
*/
{
/**
* 需要在 package.json中定义 browserslist里面的配置
*/
loader: 'postcss-loader',
options: {
// 告诉它要做哪些兼容性配置
ident: 'postcss',
plugins: () => [
/**
* postcss的插件
* 帮助 postcss找到 package.json中 browserslist里面的配置,
* 通过配置加载指定的 css兼容性样式
*/
require('postcss-preset-env')(),
],
},
},
];
// commonjs
module.exports = {
entry: ['./src/js/index.js', './src/index.html'],
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
// css代码处理
{
test: /\.css$/,
use: [
...commonCSSLoader,
// // 将 css代码提取到一个指定的文件中
// MiniCssExtractPlugin.loader,
// // 将 css加载到 js中
// 'css-loader',
// /**
// * css兼容性处理:只能针对 css代码来操作
// * postcss ->
// * postcss-loader ->
// * postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
// */
// {
// /**
// * 需要在 package.json中定义 browserslist里面的配置
// */
// loader: 'postcss-loader',
// options: {
// // 告诉它要做哪些兼容性配置
// ident: 'postcss',
// plugins: () => [
// /**
// * postcss的插件
// * 帮助 postcss找到 package.json中 browserslist里面的配置,
// * 通过配置加载指定的 css兼容性样式
// */
// require('postcss-preset-env')()
// ]
// }
// }
],
},
{
test: /\.less$/,
use: [
...commonCSSLoader,
// MiniCssExtractPlugin.loader,
// 'css-loader',
'less-loader',
],
},
/**
* 正常来讲,一个文件只能被一个 loader处理;
* 当一个文件要被多个 loader处理,那一定要指定 loader执行的先后顺序
* 如下面的 .js文件:应该先执行 eslint再执行 bable,通过 enforce属性指定
*/
// js语法检查:规范项目代码,检查常见语法错误
// {
// /**
// * 只检查源代码,忽略第三发库
// * eslint-loader
// * eslint
// * 在 package.json的 eslintConfig中设置检查规则,推荐 airbnb
// */
// test: /\.js$/,
// exclude: /node_modules/,
// // 优先执行此 loader
// enforce: 'pre',
// loader: 'eslint-loader',
// options: {
// // 自动修复 eslint错误
// fix: true,
// },
// },
// {
// // js兼容性处理:babel-loader、@babel/preset-env、@babel/core
// test: /\.js$/,
// exclude: /node_modules/,
// loader: 'babel-loader',
// options: {
// // 预设:指示 babel做怎样的兼容处理
// presets: [
// [
// // 只能作简单的语法兼容处理
// '@babel/preset-env',
// // corejs可以作复杂的语法兼容处理
// {
// // 按需加载
// useBuiltIns: 'usage',
// // 指定 core-js版本
// corejs: {
// version: 3,
// },
// // 指定兼容性做到哪个版本的浏览器
// targets: {
// chrome: '60',
// firefox: '50',
// safari: '10',
// edge: '17',
// ie: '9',
// },
// },
// ],
// ],
// },
// },
// 处理图片资源
{
test: /\.(png|gif|jpg|jpeg)$/,
loader: 'url-loader',
options: {
// 对于图片小于 8-12kb的可以进行 base64处理
limit: 8 * 1024,
// 关闭 ES6解析,使用 commonjs解析
esModule: false,
name: '[hash:10].[ext]',
outputPath: 'imgs',
},
},
// 处理 HTML中的 img资源
{
test: /\.html$/,
// 处理 HTML中的 img资源
loader: 'html-loader',
},
// 处理其它资源
{
exclude: /\.(html|js|css|less|png|gif|jpg|jpeg)/,
// 将其它资源原封不动的输出
loader: 'file-loader',
options: {
name: '[hash:10].[ext]',
outputPath: 'media',
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
// html代码压缩
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
new MiniCssExtractPlugin({
// 对提取出的 css代码放到统一的文件中,并命名
filename: 'css/built.css',
}),
// css代码压缩
new OptimizeCssAssetsWebpackPlugin(),
],
// mode: 'production',
mode: 'development',
devServer: {
contentBase: resolve(__dirname, 'build'),
compress: true,
port: 3030,
open: true,
// 开启 HRM功能
hot: true,
},
/**
* source-map的设置:
* [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
* source-map:内联
* 错误提示:错误代码准确信息和 源代码的错误位置
* inline-source-map:内联
* 1.将生成的 .map文件放在 .js文件中
* 2.只生成一个内联的 source-map文件
* 错误提示:错误代码准确信息和 源代码的错误位置
* hidden-source-map(防止源代码泄露):外联
* 1.将生成的一个 source-map文件放在单独的 .map文件中
* 错误提示:错误代码错误原因,但是没有错误位置,
* 不能追踪源代码错误,只能提示到构建后代码的错误位置
* eval-source-map:内联
* 1.针对每一个文件都生成一个单独的 source-map文件,放在 .js文件的 eval函数中
* 错误提示:错误代码准确信息 和 源代码的错误位置
* nosource-source-map(防止源代码泄露):外联
* 错误提示:错误代码准确信息, 但是没有任何源代码信息(可以防止源代码泄露)
* cheap-source-map:外联
* 错误提示:错误代码准确信息 和 源代码的错误位置,只能精确到行
* cheap-module-source-map:外联
* 错误提示:错误代码准确信息 和 源代码的错误位置,
* module会将 loader的 source-map加入
*
*/
// 开启构建后代码与源码的映射
devtool: 'eval-source-map' // development
// devtool: 'source-map' // production
};
- 运行命令:npx webpack-dev-server
oneOf
提升打包构建速度,阻止每种类型的文件都被以下 loader判断一次
- 修改配置
// nodejs
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 将 css从 js中提取出来,并到单独的文件中
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// css代码压缩
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// 定义 nodejs环境变量:决定使用 browserslist的哪个环境
// process.env.NODE_ENV = 'production'
// process.env.NODE_ENV = 'development'
// loader复用
const commonCSSLoader = [
'style-loader',
// 将 css代码提取到一个指定的文件中
// MiniCssExtractPlugin.loader,
/**
* 问题:
* MiniCssExtractPlugin.loader当前不能将 less文件单独提取出来放到指定的文件中
*/
// 将 css加载到 js中
'css-loader',
/**
* css兼容性处理:只能针对 css代码来操作
* postcss ->
* postcss-loader ->
* postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
*/
{
/**
* 需要在 package.json中定义 browserslist里面的配置
*/
loader: 'postcss-loader',
options: {
// 告诉它要做哪些兼容性配置
ident: 'postcss',
plugins: () => [
/**
* postcss的插件
* 帮助 postcss找到 package.json中 browserslist里面的配置,
* 通过配置加载指定的 css兼容性样式
*/
require('postcss-preset-env')(),
],
},
},
];
// commonjs
module.exports = {
entry: ['./src/js/index.js', './src/index.html'],
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
/**
* 只检查源代码,忽略第三发库
* eslint-loader
* eslint
* 在 package.json的 eslintConfig中设置检查规则,推荐 airbnb
*/
test: /\.js$/,
exclude: /node_modules/,
// 优先执行此 loader
enforce: 'pre',
loader: 'eslint-loader',
options: {
// 自动修复 eslint错误
fix: true,
},
},
{
/**
* oneOf:提升打包构建速度,阻止每种类型的文件都被以下 loader判断一次
* 在 oneOf中的 loader只会匹配一个
* 注意:在 oneOf中不能有两个及以上的配置处理同一种类型的文件
* 如果有,需要拿到 oneOf外边处理
*/
oneOf: [
// css代码处理
{
test: /\.css$/,
use: [
...commonCSSLoader,
/**
*
*/
// // 将 css代码提取到一个指定的文件中
// MiniCssExtractPlugin.loader,
// // 将 css加载到 js中
// 'css-loader',
// /**
// * css兼容性处理:只能针对 css代码来操作
// * postcss ->
// * postcss-loader ->
// * postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
// */
// {
// /**
// * 需要在 package.json中定义 browserslist里面的配置
// */
// loader: 'postcss-loader',
// options: {
// // 告诉它要做哪些兼容性配置
// ident: 'postcss',
// plugins: () => [
// /**
// * postcss的插件
// * 帮助 postcss找到 package.json中 browserslist里面的配置,
// * 通过配置加载指定的 css兼容性样式
// */
// require('postcss-preset-env')()
// ]
// }
// }
],
},
{
test: /\.less$/,
use: [
...commonCSSLoader,
// MiniCssExtractPlugin.loader,
// 'css-loader',
'less-loader',
],
},
/**
* 正常来讲,一个文件只能被一个 loader处理;
* 当一个文件要被多个 loader处理,那一定要指定 loader执行的先后顺序
* 如下面的 .js文件:应该先执行 eslint再执行 bable,通过 enforce属性指定
*/
// js语法检查:规范项目代码,检查常见语法错误
{
// js兼容性处理:babel-loader、@babel/preset-env、@babel/core
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// 预设:指示 babel做怎样的兼容处理
presets: [
[
// 只能作简单的语法兼容处理
'@babel/preset-env',
// corejs可以作复杂的语法兼容处理
{
// 按需加载
useBuiltIns: 'usage',
// 指定 core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪个版本的浏览器
targets: {
chrome: '60',
firefox: '50',
safari: '10',
edge: '17',
ie: '9',
},
},
],
],
},
},
// 处理图片资源
{
test: /\.(png|gif|jpg|jpeg)$/,
loader: 'url-loader',
options: {
// 对于图片小于 8-12kb的可以进行 base64处理
limit: 8 * 1024,
// 关闭 ES6解析,使用 commonjs解析
esModule: false,
name: '[hash:10].[ext]',
outputPath: 'imgs',
},
},
// 处理 HTML中的 img资源
{
test: /\.html$/,
// 处理 HTML中的 img资源
loader: 'html-loader',
},
// 处理其它资源
{
exclude: /\.(html|js|css|less|png|gif|jpg|jpeg)/,
// 将其它资源原封不动的输出
loader: 'file-loader',
options: {
name: '[hash:10].[ext]',
outputPath: 'media',
},
},
],
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
// html代码压缩
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
new MiniCssExtractPlugin({
// 对提取出的 css代码放到统一的文件中,并命名
filename: 'css/built.css',
}),
// css代码压缩
new OptimizeCssAssetsWebpackPlugin(),
],
// mode: 'production',
mode: 'development',
devServer: {
contentBase: resolve(__dirname, 'build'),
compress: true,
port: 3030,
open: true,
// 开启 HRM功能
hot: true,
},
/**
* source-map的设置:
* [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
* source-map:内联
* 错误提示:错误代码准确信息和 源代码的错误位置
* inline-source-map:内联
* 1.将生成的 .map文件放在 .js文件中
* 2.只生成一个内联的 source-map文件
* 错误提示:错误代码准确信息和 源代码的错误位置
* hidden-source-map(防止源代码泄露):外联
* 1.将生成的一个 source-map文件放在单独的 .map文件中
* 错误提示:错误代码错误原因,但是没有错误位置,
* 不能追踪源代码错误,只能提示到构建后代码的错误位置
* eval-source-map:内联
* 1.针对每一个文件都生成一个单独的 source-map文件,放在 .js文件的 eval函数中
* 错误提示:错误代码准确信息 和 源代码的错误位置
* nosource-source-map(防止源代码泄露):外联
* 错误提示:错误代码准确信息, 但是没有任何源代码信息(可以防止源代码泄露)
* cheap-source-map:外联
* 错误提示:错误代码准确信息 和 源代码的错误位置,只能精确到行
* cheap-module-source-map:外联
* 错误提示:错误代码准确信息 和 源代码的错误位置,
* module会将 loader的 source-map加入
*
*/
// 开启构建后代码与源码的映射
devtool: 'eval-source-map' // development
// devtool: 'source-map' // production
};
缓存 -23
babel缓存:cacheDirectory: true
将 babel编译的 js文件进行缓存,当第二次及以后打包构建时使用缓存,只对有修改的 js文件进行重新编译;使得除第一次外以后的打包更快
{
// js兼容性处理:babel-loader、@babel/preset-env、@babel/core
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// 预设:指示 babel做怎样的兼容处理
presets: [
[
// 只能作简单的语法兼容处理
'@babel/preset-env',
// corejs可以作复杂的语法兼容处理
{
// 按需加载
useBuiltIns: 'usage',
// 指定 core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪个版本的浏览器
targets: {
chrome: '60',
firefox: '50',
safari: '10',
edge: '17',
ie: '9',
},
},
],
],
/**
* 开启 babel缓存
* 第二次构建时,会读取缓存,提升构建速度
*/
cacheDirectory: true
},
},
文件资源缓存
hash:(有问题)
每次 webpack构建时会生成一个唯一的 hash值
- 问题:因 js和 css同时使用一个 hash值;如果重新打包,会导致所有缓存失效(只改变一个文件的情况下)
chunkhash:(有问题)
所有根据入口文件引入的文件会生成一个 chunk;
根据 chunk生成的 hash值;如果打包来源于同一个 chunk,那 hash值就一样
- 问题:js和 css的 hash值相同,因为 css是在 js中提取出来的,属于同一个 chunk
contenthash:(解决)
根据文件的内容来生成 hash值,所以不同的文件 hash值一定不同
- 让代码上线后,缓存更好使用
结果:
- 修改配置文件
// nodejs
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 将 css从 js中提取出来,并到单独的文件中
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// css代码压缩
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// 定义 nodejs环境变量:决定使用 browserslist的哪个环境
// process.env.NODE_ENV = 'production'
// process.env.NODE_ENV = 'development'
// loader复用
const commonCSSLoader = [
// 'style-loader',
// 将 css代码提取到一个指定的文件中
MiniCssExtractPlugin.loader,
/**
* 问题:
* MiniCssExtractPlugin.loader当前不能将 less文件单独提取出来放到指定的文件中
*/
// 将 css加载到 js中
'css-loader',
/**
* css兼容性处理:只能针对 css代码来操作
* postcss ->
* postcss-loader ->
* postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
*/
{
/**
* 需要在 package.json中定义 browserslist里面的配置
*/
loader: 'postcss-loader',
options: {
// 告诉它要做哪些兼容性配置
ident: 'postcss',
plugins: () => [
/**
* postcss的插件
* 帮助 postcss找到 package.json中 browserslist里面的配置,
* 通过配置加载指定的 css兼容性样式
*/
require('postcss-preset-env')(),
],
},
},
];
// commonjs
module.exports = {
entry: ['./src/js/index.js', './src/index.html'],
output: {
/**
* 给文件添加 hash值,防止缓存:[hash:8]
*/
filename: 'js/built.[contenthash:8].js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
/**
* 只检查源代码,忽略第三发库
* eslint-loader
* eslint
* 在 package.json的 eslintConfig中设置检查规则,推荐 airbnb
*/
test: /\.js$/,
exclude: /node_modules/,
// 优先执行此 loader
enforce: 'pre',
loader: 'eslint-loader',
options: {
// 自动修复 eslint错误
fix: true,
},
},
{
/**
* oneOf:提升打包构建速度,阻止每种类型的文件都被以下 loader判断一次
* 在 oneOf中的 loader只会匹配一个
* 注意:在 oneOf中不能有两个及以上的配置处理同一种类型的文件
* 如果有,需要拿到 oneOf外边处理
*/
oneOf: [
// css代码处理
{
test: /\.css$/,
use: [
...commonCSSLoader,
/**
*
*/
// // 将 css代码提取到一个指定的文件中
// MiniCssExtractPlugin.loader,
// // 将 css加载到 js中
// 'css-loader',
// /**
// * css兼容性处理:只能针对 css代码来操作
// * postcss ->
// * postcss-loader ->
// * postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
// */
// {
// /**
// * 需要在 package.json中定义 browserslist里面的配置
// */
// loader: 'postcss-loader',
// options: {
// // 告诉它要做哪些兼容性配置
// ident: 'postcss',
// plugins: () => [
// /**
// * postcss的插件
// * 帮助 postcss找到 package.json中 browserslist里面的配置,
// * 通过配置加载指定的 css兼容性样式
// */
// require('postcss-preset-env')()
// ]
// }
// }
],
},
{
test: /\.less$/,
use: [
...commonCSSLoader,
// MiniCssExtractPlugin.loader,
// 'css-loader',
'less-loader',
],
},
/**
* 正常来讲,一个文件只能被一个 loader处理;
* 当一个文件要被多个 loader处理,那一定要指定 loader执行的先后顺序
* 如下面的 .js文件:应该先执行 eslint再执行 bable,通过 enforce属性指定
*/
// js语法检查:规范项目代码,检查常见语法错误
{
// js兼容性处理:babel-loader、@babel/preset-env、@babel/core
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// 预设:指示 babel做怎样的兼容处理
presets: [
[
// 只能作简单的语法兼容处理
'@babel/preset-env',
// corejs可以作复杂的语法兼容处理
{
// 按需加载
useBuiltIns: 'usage',
// 指定 core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪个版本的浏览器
targets: {
chrome: '60',
firefox: '50',
safari: '10',
edge: '17',
ie: '9',
},
},
],
],
/**
* 开启 babel缓存
* 第二次构建时,会读取缓存,提升构建速度
*/
cacheDirectory: true
},
},
// 处理图片资源
{
test: /\.(png|gif|jpg|jpeg)$/,
loader: 'url-loader',
options: {
// 对于图片小于 8-12kb的可以进行 base64处理
limit: 8 * 1024,
// 关闭 ES6解析,使用 commonjs解析
esModule: false,
name: '[hash:10].[ext]',
outputPath: 'imgs',
},
},
// 处理 HTML中的 img资源
{
test: /\.html$/,
// 处理 HTML中的 img资源
loader: 'html-loader',
},
// 处理其它资源
{
exclude: /\.(html|js|css|less|png|gif|jpg|jpeg)/,
// 将其它资源原封不动的输出
loader: 'file-loader',
options: {
name: '[hash:10].[ext]',
outputPath: 'media',
},
},
],
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
// html代码压缩
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
new MiniCssExtractPlugin({
// 对提取出的 css代码放到统一的文件中,并命名
filename: 'css/built.[contenthash:8].css',
}),
// css代码压缩
new OptimizeCssAssetsWebpackPlugin(),
],
// mode: 'production',
mode: 'development',
devServer: {
contentBase: resolve(__dirname, 'build'),
compress: true,
port: 3030,
open: true,
// 开启 HRM功能
hot: true,
},
/**
* source-map的设置:
* [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
* source-map:内联
* 错误提示:错误代码准确信息和 源代码的错误位置
* inline-source-map:内联
* 1.将生成的 .map文件放在 .js文件中
* 2.只生成一个内联的 source-map文件
* 错误提示:错误代码准确信息和 源代码的错误位置
* hidden-source-map(防止源代码泄露):外联
* 1.将生成的一个 source-map文件放在单独的 .map文件中
* 错误提示:错误代码错误原因,但是没有错误位置,
* 不能追踪源代码错误,只能提示到构建后代码的错误位置
* eval-source-map:内联
* 1.针对每一个文件都生成一个单独的 source-map文件,放在 .js文件的 eval函数中
* 错误提示:错误代码准确信息 和 源代码的错误位置
* nosource-source-map(防止源代码泄露):外联
* 错误提示:错误代码准确信息, 但是没有任何源代码信息(可以防止源代码泄露)
* cheap-source-map:外联
* 错误提示:错误代码准确信息 和 源代码的错误位置,只能精确到行
* cheap-module-source-map:外联
* 错误提示:错误代码准确信息 和 源代码的错误位置,
* module会将 loader的 source-map加入
*
*/
// 开启构建后代码与源码的映射
devtool: 'eval-source-map' // development
// devtool: 'source-map' // production
};
- 编写 node服务
// server.js
/**
* 服务器代码:查看缓存
* 启动服务器指令:
* npm i nodemon -g
* nodemon server.js 或
* node server.js
* 访问服务器地址:
* http://localhost:3080
*/
// 使用express搭建
const express = require('express')
// 1.创建 express对象
const app = express()
// 2.使用中间件,暴露 'build'文件
app.use(express.static('build', { maxAge: 1000 * 3600 }))
// 3.启动此服务器
app.listen(3080)
- 运行指令:npx webpack
- 开启nodejs服务:node server.js
tree shaking:去除应用中无用代码 -24
去除在项目中只引入而没有使用的源代码、下载的第三方库
- 作用:减少代码体积
前提条件:
- 必须使用 ES6模块化
- 开启 'production'环境
问题:
- 在 package.json中配置 "sideEffects": false 所有代码都没有副作用(都可以进行 tree shaking)
- 可能会将 css、@babel/polyfill等文件忽略,并干掉
- 应作如下配置:(避免有些文件被干掉)
// package.json "sideEffects": [ "*.css", "*.less" ]
code split
方式一:(不推荐)
将应用改为 多入口文件
// 多入口 -> 多页面应用
// 根据入口的个数最终输出 bundle的个数
entry: {
index: './src/js/index.js',
test: './src/js/test.js'
},
方式二:使用 optimization的 splitChunks属性
- 将 node_modules中代码单独打包成一个 chunk最终输出
- 保证多处引入同一个第三方模块只被打包一次
/**
* code split:代码拆分
* 方式二:splitChunks
* 作用:
* 1.将 node_modules中代码单独打包成一个 chunk最终输出
* 2.保证多处引入同一个第三方模块只被打包一次
*/
optimization: {
splitChunks: {
chunks: 'all'
}
},
方式三:通过 js代码 import语法,使得引入的文件被单独打包成一个 chunk
- /* webpackChunkName: 'test' */:用于命名被打包后的文件
// index.js
/**
* code split:代码拆分
* 方式三:通过 js代码,使得引入的文件被单独打包成一个 chunk
*/
// /* webpackChunkName: 'test' */:用于命名被打包后的文件
import(/* webpackChunkName: 'test' */'./test')
.then((res) => {
console.log('test', res)
})
.catch(() => {
console.log('文件加载失败!')
})
总结:
在实际开发中一般通过,方式二和方式三 结合的方式完成代码分割
- 修改配置文件
// nodejs
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 将 css从 js中提取出来,并到单独的文件中
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// css代码压缩
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// 定义 nodejs环境变量:决定使用 browserslist的哪个环境
// process.env.NODE_ENV = 'production'
// process.env.NODE_ENV = 'development'
// loader复用
const commonCSSLoader = [
// 'style-loader',
// 将 css代码提取到一个指定的文件中
MiniCssExtractPlugin.loader,
/**
* 问题:
* MiniCssExtractPlugin.loader当前不能将 less文件单独提取出来放到指定的文件中
*/
// 将 css加载到 js中
'css-loader',
/**
* css兼容性处理:只能针对 css代码来操作
* postcss ->
* postcss-loader ->
* postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
*/
{
/**
* 需要在 package.json中定义 browserslist里面的配置
*/
loader: 'postcss-loader',
options: {
// 告诉它要做哪些兼容性配置
ident: 'postcss',
plugins: () => [
/**
* postcss的插件
* 帮助 postcss找到 package.json中 browserslist里面的配置,
* 通过配置加载指定的 css兼容性样式
*/
require('postcss-preset-env')(),
],
},
},
];
// commonjs
module.exports = {
// 单入口 -> 单页面应用
entry: './src/js/index.js',
/**
* code split:代码拆分
* 方式一:修改入口文件:(不推荐)
*/
// 多入口 -> 多页面应用
// 根据入口的个数最终输出 bundle的个数
// entry: {
// index: './src/js/index.js',
// test: './src/js/test.js'
// },
output: {
/**
* 给文件添加 hash值,防止缓存:[hash:8]
*/
filename: 'js/[name].[contenthash:8].js',
path: resolve(__dirname, 'build'),
},
/**
* code split:代码拆分
* 方式二:splitChunks
* 作用:
* 1.将 node_modules中代码单独打包成一个 chunk最终输出
* 2.保证多处引入同一个第三方模块只被打包一次
*/
optimization: {
splitChunks: {
chunks: 'all'
}
},
module: {
rules: [
// {
// /**
// * 只检查源代码,忽略第三发库
// * eslint-loader
// * eslint
// * 在 package.json的 eslintConfig中设置检查规则,推荐 airbnb
// */
// test: /\.js$/,
// exclude: /node_modules/,
// // 优先执行此 loader
// enforce: 'pre',
// loader: 'eslint-loader',
// options: {
// // 自动修复 eslint错误
// fix: true,
// },
// },
{
/**
* oneOf:提升打包构建速度,阻止每种类型的文件都被以下 loader判断一次
* 在 oneOf中的 loader只会匹配一个
* 注意:在 oneOf中不能有两个及以上的配置处理同一种类型的文件
* 如果有,需要拿到 oneOf外边处理
*/
oneOf: [
// css代码处理
{
test: /\.css$/,
use: [
...commonCSSLoader,
/**
*
*/
// // 将 css代码提取到一个指定的文件中
// MiniCssExtractPlugin.loader,
// // 将 css加载到 js中
// 'css-loader',
// /**
// * css兼容性处理:只能针对 css代码来操作
// * postcss ->
// * postcss-loader ->
// * postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
// */
// {
// /**
// * 需要在 package.json中定义 browserslist里面的配置
// */
// loader: 'postcss-loader',
// options: {
// // 告诉它要做哪些兼容性配置
// ident: 'postcss',
// plugins: () => [
// /**
// * postcss的插件
// * 帮助 postcss找到 package.json中 browserslist里面的配置,
// * 通过配置加载指定的 css兼容性样式
// */
// require('postcss-preset-env')()
// ]
// }
// }
],
},
{
test: /\.less$/,
use: [
...commonCSSLoader,
// MiniCssExtractPlugin.loader,
// 'css-loader',
'less-loader',
],
},
/**
* 正常来讲,一个文件只能被一个 loader处理;
* 当一个文件要被多个 loader处理,那一定要指定 loader执行的先后顺序
* 如下面的 .js文件:应该先执行 eslint再执行 bable,通过 enforce属性指定
*/
// js语法检查:规范项目代码,检查常见语法错误
{
// js兼容性处理:babel-loader、@babel/preset-env、@babel/core
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// 预设:指示 babel做怎样的兼容处理
presets: [
[
// 只能作简单的语法兼容处理
'@babel/preset-env',
// corejs可以作复杂的语法兼容处理
{
// 按需加载
useBuiltIns: 'usage',
// 指定 core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪个版本的浏览器
targets: {
chrome: '60',
firefox: '50',
safari: '10',
edge: '17',
ie: '9',
},
},
],
],
/**
* 开启 babel缓存
* 第二次构建时,会读取缓存,提升构建速度
*/
cacheDirectory: true
},
},
// 处理图片资源
{
test: /\.(png|gif|jpg|jpeg)$/,
loader: 'url-loader',
options: {
// 对于图片小于 8-12kb的可以进行 base64处理
limit: 8 * 1024,
// 关闭 ES6解析,使用 commonjs解析
esModule: false,
name: '[hash:10].[ext]',
outputPath: 'imgs',
},
},
// 处理 HTML中的 img资源
{
test: /\.html$/,
// 处理 HTML中的 img资源
loader: 'html-loader',
},
// 处理其它资源
{
exclude: /\.(html|js|css|less|png|gif|jpg|jpeg)/,
// 将其它资源原封不动的输出
loader: 'file-loader',
options: {
name: '[hash:10].[ext]',
outputPath: 'media',
},
},
],
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
// html代码压缩
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
new MiniCssExtractPlugin({
// 对提取出的 css代码放到统一的文件中,并命名
filename: 'css/built.[contenthash:8].css',
}),
// css代码压缩
new OptimizeCssAssetsWebpackPlugin(),
],
mode: 'production',
// mode: 'development',
devServer: {
contentBase: resolve(__dirname, 'build'),
compress: true,
port: 3030,
open: true,
// 开启 HRM功能
hot: true,
},
/**
* source-map的设置:
* [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
* source-map:内联
* 错误提示:错误代码准确信息和 源代码的错误位置
* inline-source-map:内联
* 1.将生成的 .map文件放在 .js文件中
* 2.只生成一个内联的 source-map文件
* 错误提示:错误代码准确信息和 源代码的错误位置
* hidden-source-map(防止源代码泄露):外联
* 1.将生成的一个 source-map文件放在单独的 .map文件中
* 错误提示:错误代码错误原因,但是没有错误位置,
* 不能追踪源代码错误,只能提示到构建后代码的错误位置
* eval-source-map:内联
* 1.针对每一个文件都生成一个单独的 source-map文件,放在 .js文件的 eval函数中
* 错误提示:错误代码准确信息 和 源代码的错误位置
* nosource-source-map(防止源代码泄露):外联
* 错误提示:错误代码准确信息, 但是没有任何源代码信息(可以防止源代码泄露)
* cheap-source-map:外联
* 错误提示:错误代码准确信息 和 源代码的错误位置,只能精确到行
* cheap-module-source-map:外联
* 错误提示:错误代码准确信息 和 源代码的错误位置,
* module会将 loader的 source-map加入
*
*/
// 开启构建后代码与源码的映射
devtool: 'eval-source-map' // development
// devtool: 'source-map' // production
};
- index.js
import $ from 'jquery';
import print from './print';
// import { mul } from './test';
import '../css/iconfont.css';
import '../css/a.css';
import '../css/b.less';
/**
* code split:代码拆分
* 方式三:通过 js代码,使得引入的文件被单独打包成一个 chunk
*/
// /* webpackChunkName: 'test' */:用于命名被打包后的文件
import(/* webpackChunkName: 'test' */'./test')
.then((res) => {
console.log('test', res)
})
.catch(() => {
console.log('文件加载失败!')
})
const add = (x, y) => x + y;
console.log(add(1, 4));
// console.log(res.mul(1, 2));
if (module.hot) {
// 一旦 module.hot为 true,说明开启了 HMR功能 -> 让 HMR功能代码生效
module.hot.accept('./print.js', () => {
/**
* 方法会监听 print.js文件变化,一旦发生变化,其它模块不会重新打包
* 会执行后面的回调函数
*/
print();
});
}
console.log($);
- 运行指令:npx webpack
lazy loading:js文件懒加载 -26
利用代码分割的思路,将要被懒加载的 文件放到异步回调函数中,通过代码分割 import函数引入文件,当满足异步函数触发条件时加载对应的文件
注意:实现 懒加载的前提是先进行 代码分割
- 正常加载:并行加载(同一时间加载多个文件)
- http协议,同一个域名只能同时加载六个文件
- 懒加载:当文件被使用时才加载
- 预加载 prefetch(
不推荐):在使用之前,提前加载 js文件 webpackPrefetch: true- 等其它资源加载完毕,浏览器再偷偷加载 预加载资源
- 只在 pc端可用,ie和移动端有兼容问题
// index.js
/**
* lazy loading
*/
document.getElementById('btn').onclick = function () {
// 此时 .test就会变成懒加载
import(/* webpackChunkName: 'test', webpackPrefetch: true */'./test')
.then(({ mul }) => {
console.log(mul(1, 3))
})
}
pwa:渐进式网络开发应用程序(离线可访问)
使得网页可以像 app一样,可以离线访问,性能也更好
配置:
- 在 webpack.config.js中下载插件:workbox-webpack-plugin
plugins: [ /** * pwa: * 1.帮助 serviceworker快速启动 * 2.删除旧的 serviceworker * 最终:生成一个 serviceworker配置文件 * 然后在入口文件中注册 serviceworker */ new WorkboxWebpackPlugin.GenerateSW({ clientsClaim: true, skipWaiting: true }) ] - 在入口文件中 index.js注册 serviceWorker
/**
* 注册 serviceworker:
* 处理兼容性问题
*/
/**
* 问题:
* 1.eslint不认识全局变量:window、navigator...
* 需要设置 eslintConfig的 env属性
*
* 2.serviceworker代码必须运行在服务器上
* -1. nodejs
* -2. npm i serve -g,快速创建一个服务器
* 运行 serve -s build,启动服务器,将 build目录下所有资源作为静态资源暴露出去
*/
if ('serviceWorker' in navigator) {
// 全部资源加载完成后
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then(() => {
console.log('sw success');
})
.catch(() => {
console.log('sw fail');
});
});
}
- 解决一些问题:
- eslint
/*
1.eslint不认识全局变量:window、navigator...
需要设置 eslintConfig的 env属性
*/
"eslintConfig": {
"extends": "airbnb-base",
"env": {
"browser": true
}
},
- 开启服务器
// 2.开启服务器
/* 2.serviceworker代码必须运行在服务器上
* -1. nodejs
* -2. npm i serve -g,快速创建一个服务器
* 运行 serve -s build,启动服务器,将 build目录下所有资源作为静态资源暴露出去
*/
- 修改配置文件
// nodejs
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 将 css从 js中提取出来,并到单独的文件中
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// css代码压缩
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// pwa
const WorkboxWebpackPlugin = require('workbox-webpack-plugin')
// 定义 nodejs环境变量:决定使用 browserslist的哪个环境
// process.env.NODE_ENV = 'production'
// process.env.NODE_ENV = 'development'
// loader复用
const commonCSSLoader = [
// 'style-loader',
// 将 css代码提取到一个指定的文件中
MiniCssExtractPlugin.loader,
/**
* 问题:
* MiniCssExtractPlugin.loader当前不能将 less文件单独提取出来放到指定的文件中
*/
// 将 css加载到 js中
'css-loader',
/**
* css兼容性处理:只能针对 css代码来操作
* postcss ->
* postcss-loader ->
* postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
*/
{
/**
* 需要在 package.json中定义 browserslist里面的配置
*/
loader: 'postcss-loader',
options: {
// 告诉它要做哪些兼容性配置
ident: 'postcss',
plugins: () => [
/**
* postcss的插件
* 帮助 postcss找到 package.json中 browserslist里面的配置,
* 通过配置加载指定的 css兼容性样式
*/
require('postcss-preset-env')(),
],
},
},
];
// commonjs
module.exports = {
entry: ['./src/js/index.js', './src/index.html'],
output: {
/**
* 给文件添加 hash值,防止缓存:[hash:8]
*/
filename: 'js/built.[contenthash:8].js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
/**
* 只检查源代码,忽略第三发库
* eslint-loader
* eslint
* 在 package.json的 eslintConfig中设置检查规则,推荐 airbnb
*/
test: /\.js$/,
exclude: /node_modules/,
// 优先执行此 loader
enforce: 'pre',
loader: 'eslint-loader',
options: {
// 自动修复 eslint错误
fix: true,
},
},
{
/**
* oneOf:提升打包构建速度,阻止每种类型的文件都被以下 loader判断一次
* 在 oneOf中的 loader只会匹配一个
* 注意:在 oneOf中不能有两个及以上的配置处理同一种类型的文件
* 如果有,需要拿到 oneOf外边处理
*/
oneOf: [
// css代码处理
{
test: /\.css$/,
use: [
...commonCSSLoader,
/**
*
*/
// // 将 css代码提取到一个指定的文件中
// MiniCssExtractPlugin.loader,
// // 将 css加载到 js中
// 'css-loader',
// /**
// * css兼容性处理:只能针对 css代码来操作
// * postcss ->
// * postcss-loader ->
// * postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
// */
// {
// /**
// * 需要在 package.json中定义 browserslist里面的配置
// */
// loader: 'postcss-loader',
// options: {
// // 告诉它要做哪些兼容性配置
// ident: 'postcss',
// plugins: () => [
// /**
// * postcss的插件
// * 帮助 postcss找到 package.json中 browserslist里面的配置,
// * 通过配置加载指定的 css兼容性样式
// */
// require('postcss-preset-env')()
// ]
// }
// }
],
},
{
test: /\.less$/,
use: [
...commonCSSLoader,
// MiniCssExtractPlugin.loader,
// 'css-loader',
'less-loader',
],
},
/**
* 正常来讲,一个文件只能被一个 loader处理;
* 当一个文件要被多个 loader处理,那一定要指定 loader执行的先后顺序
* 如下面的 .js文件:应该先执行 eslint再执行 bable,通过 enforce属性指定
*/
// js语法检查:规范项目代码,检查常见语法错误
{
// js兼容性处理:babel-loader、@babel/preset-env、@babel/core
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// 预设:指示 babel做怎样的兼容处理
presets: [
[
// 只能作简单的语法兼容处理
'@babel/preset-env',
// corejs可以作复杂的语法兼容处理
{
// 按需加载
useBuiltIns: 'usage',
// 指定 core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪个版本的浏览器
targets: {
chrome: '60',
firefox: '50',
safari: '10',
edge: '17',
ie: '9',
},
},
],
],
/**
* 开启 babel缓存
* 第二次构建时,会读取缓存,提升构建速度
*/
cacheDirectory: true
},
},
// 处理图片资源
{
test: /\.(png|gif|jpg|jpeg)$/,
loader: 'url-loader',
options: {
// 对于图片小于 8-12kb的可以进行 base64处理
limit: 8 * 1024,
// 关闭 ES6解析,使用 commonjs解析
esModule: false,
name: '[hash:10].[ext]',
outputPath: 'imgs',
},
},
// 处理 HTML中的 img资源
{
test: /\.html$/,
// 处理 HTML中的 img资源
loader: 'html-loader',
},
// 处理其它资源
{
exclude: /\.(html|js|css|less|png|gif|jpg|jpeg)/,
// 将其它资源原封不动的输出
loader: 'file-loader',
options: {
name: '[hash:10].[ext]',
outputPath: 'media',
},
},
],
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
// html代码压缩
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
new MiniCssExtractPlugin({
// 对提取出的 css代码放到统一的文件中,并命名
filename: 'css/built.[contenthash:8].css',
}),
// css代码压缩
new OptimizeCssAssetsWebpackPlugin(),
/**
* pwa:
* 1.帮助 serviceworker快速启动
* 2.删除旧的 serviceworker
* 最终:生成一个 serviceworker配置文件
* 然后在入口文件中注册 serviceworker
*/
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
skipWaiting: true
})
],
mode: 'production',
// mode: 'development',
devServer: {
contentBase: resolve(__dirname, 'build'),
compress: true,
port: 3030,
open: true,
// 开启 HRM功能
hot: true,
},
/**
* source-map的设置:
* [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
* source-map:内联
* 错误提示:错误代码准确信息和 源代码的错误位置
* inline-source-map:内联
* 1.将生成的 .map文件放在 .js文件中
* 2.只生成一个内联的 source-map文件
* 错误提示:错误代码准确信息和 源代码的错误位置
* hidden-source-map(防止源代码泄露):外联
* 1.将生成的一个 source-map文件放在单独的 .map文件中
* 错误提示:错误代码错误原因,但是没有错误位置,
* 不能追踪源代码错误,只能提示到构建后代码的错误位置
* eval-source-map:内联
* 1.针对每一个文件都生成一个单独的 source-map文件,放在 .js文件的 eval函数中
* 错误提示:错误代码准确信息 和 源代码的错误位置
* nosource-source-map(防止源代码泄露):外联
* 错误提示:错误代码准确信息, 但是没有任何源代码信息(可以防止源代码泄露)
* cheap-source-map:外联
* 错误提示:错误代码准确信息 和 源代码的错误位置,只能精确到行
* cheap-module-source-map:外联
* 错误提示:错误代码准确信息 和 源代码的错误位置,
* module会将 loader的 source-map加入
*
*/
// 开启构建后代码与源码的映射
devtool: 'eval-source-map' // development
// devtool: 'source-map' // production
};
- index.js入口文件
import print from './print';
import { mul } from './test';
import '../css/iconfont.css';
import '../css/a.css';
import '../css/b.less';
const add = (x, y) => x + y;
console.log(add(1, 4));
console.log(mul(1, 2));
if (module.hot) {
// 一旦 module.hot为 true,说明开启了 HMR功能 -> 让 HMR功能代码生效
module.hot.accept('./print.js', () => {
/**
* 方法会监听 print.js文件变化,一旦发生变化,其它模块不会重新打包
* 会执行后面的回调函数
*/
print();
});
}
/**
* 注册 serviceworker:
* 处理兼容性问题
*/
/**
* 问题:
* 1.eslint不认识全局变量:window、navigator...
* 需要设置 eslintConfig的 env属性
*
* 2.serviceworker代码必须运行在服务器上
* -1. nodejs
* -2. npm i serve -g,快速创建一个服务器
* 运行 serve -s build,启动服务器,将 build目录下所有资源作为静态资源暴露出去
*/
if ('serviceWorker' in navigator) {
// 全部资源加载完成后
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then(() => {
console.log('sw success');
})
.catch(() => {
console.log('sw fail');
});
});
}
多进程打包
主要是用于 babel-loader,开启多进程打包
问题:
- 进程启动大概需要 600ms,另外进程通信也有开销
- 只有工作消耗时间较长,才需要多进程打包
配置
- 下载安装包
npm install --save-dev thread-loader
- 修改配置文件
// nodejs
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 将 css从 js中提取出来,并到单独的文件中
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// css代码压缩
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// pwa
const WorkboxWebpackPlugin = require('workbox-webpack-plugin')
// 定义 nodejs环境变量:决定使用 browserslist的哪个环境
// process.env.NODE_ENV = 'production'
// process.env.NODE_ENV = 'development'
// loader复用
const commonCSSLoader = [
// 'style-loader',
// 将 css代码提取到一个指定的文件中
MiniCssExtractPlugin.loader,
/**
* 问题:
* MiniCssExtractPlugin.loader当前不能将 less文件单独提取出来放到指定的文件中
*/
// 将 css加载到 js中
'css-loader',
/**
* css兼容性处理:只能针对 css代码来操作
* postcss ->
* postcss-loader ->
* postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
*/
{
/**
* 需要在 package.json中定义 browserslist里面的配置
*/
loader: 'postcss-loader',
options: {
// 告诉它要做哪些兼容性配置
ident: 'postcss',
plugins: () => [
/**
* postcss的插件
* 帮助 postcss找到 package.json中 browserslist里面的配置,
* 通过配置加载指定的 css兼容性样式
*/
require('postcss-preset-env')(),
],
},
},
];
// commonjs
module.exports = {
entry: ['./src/js/index.js', './src/index.html'],
output: {
/**
* 给文件添加 hash值,防止缓存:[hash:8]
*/
filename: 'js/built.[contenthash:8].js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
/**
* 只检查源代码,忽略第三发库
* eslint-loader
* eslint
* 在 package.json的 eslintConfig中设置检查规则,推荐 airbnb
*/
test: /\.js$/,
exclude: /node_modules/,
// 优先执行此 loader
enforce: 'pre',
loader: 'eslint-loader',
options: {
// 自动修复 eslint错误
fix: true,
},
},
{
/**
* oneOf:提升打包构建速度,阻止每种类型的文件都被以下 loader判断一次
* 在 oneOf中的 loader只会匹配一个
* 注意:在 oneOf中不能有两个及以上的配置处理同一种类型的文件
* 如果有,需要拿到 oneOf外边处理
*/
oneOf: [
// css代码处理
{
test: /\.css$/,
use: [
...commonCSSLoader,
/**
*
*/
// // 将 css代码提取到一个指定的文件中
// MiniCssExtractPlugin.loader,
// // 将 css加载到 js中
// 'css-loader',
// /**
// * css兼容性处理:只能针对 css代码来操作
// * postcss ->
// * postcss-loader ->
// * postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
// */
// {
// /**
// * 需要在 package.json中定义 browserslist里面的配置
// */
// loader: 'postcss-loader',
// options: {
// // 告诉它要做哪些兼容性配置
// ident: 'postcss',
// plugins: () => [
// /**
// * postcss的插件
// * 帮助 postcss找到 package.json中 browserslist里面的配置,
// * 通过配置加载指定的 css兼容性样式
// */
// require('postcss-preset-env')()
// ]
// }
// }
],
},
{
test: /\.less$/,
use: [
...commonCSSLoader,
// MiniCssExtractPlugin.loader,
// 'css-loader',
'less-loader',
],
},
/**
* 正常来讲,一个文件只能被一个 loader处理;
* 当一个文件要被多个 loader处理,那一定要指定 loader执行的先后顺序
* 如下面的 .js文件:应该先执行 eslint再执行 bable,通过 enforce属性指定
*/
// js语法检查:规范项目代码,检查常见语法错误
{
// js兼容性处理:babel-loader、@babel/preset-env、@babel/core
test: /\.js$/,
exclude: /node_modules/,
use: [
/**
* 开启多进程打包:
*/
{
loader: 'thread-loader',
options: {
workers: 2 // 规定只开启两个进程,默认是 cpu核数 - 1
}
},
{
loader: 'babel-loader',
options: {
// 预设:指示 babel做怎样的兼容处理
presets: [
[
// 只能作简单的语法兼容处理
'@babel/preset-env',
// corejs可以作复杂的语法兼容处理
{
// 按需加载
useBuiltIns: 'usage',
// 指定 core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪个版本的浏览器
targets: {
chrome: '60',
firefox: '50',
safari: '10',
edge: '17',
ie: '9',
},
},
],
],
/**
* 开启 babel缓存
* 第二次构建时,会读取缓存,提升构建速度
*/
cacheDirectory: true
},
}
],
},
// 处理图片资源
{
test: /\.(png|gif|jpg|jpeg)$/,
loader: 'url-loader',
options: {
// 对于图片小于 8-12kb的可以进行 base64处理
limit: 8 * 1024,
// 关闭 ES6解析,使用 commonjs解析
esModule: false,
name: '[hash:10].[ext]',
outputPath: 'imgs',
},
},
// 处理 HTML中的 img资源
{
test: /\.html$/,
// 处理 HTML中的 img资源
loader: 'html-loader',
},
// 处理其它资源
{
exclude: /\.(html|js|css|less|png|gif|jpg|jpeg)/,
// 将其它资源原封不动的输出
loader: 'file-loader',
options: {
name: '[hash:10].[ext]',
outputPath: 'media',
},
},
],
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
// html代码压缩
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
new MiniCssExtractPlugin({
// 对提取出的 css代码放到统一的文件中,并命名
filename: 'css/built.[contenthash:8].css',
}),
// css代码压缩
new OptimizeCssAssetsWebpackPlugin(),
/**
* pwa:
* 1.帮助 serviceworker快速启动
* 2.删除旧的 serviceworker
* 最终:生成一个 serviceworker配置文件
* 然后在入口文件中注册 serviceworker
*/
// new WorkboxWebpackPlugin.GenerateSW({
// clientsClaim: true,
// skipWaiting: true
// })
],
mode: 'production',
// mode: 'development',
devServer: {
contentBase: resolve(__dirname, 'build'),
compress: true,
port: 3030,
open: true,
// 开启 HRM功能
hot: true,
},
/**
* source-map的设置:
* [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
* source-map:内联
* 错误提示:错误代码准确信息和 源代码的错误位置
* inline-source-map:内联
* 1.将生成的 .map文件放在 .js文件中
* 2.只生成一个内联的 source-map文件
* 错误提示:错误代码准确信息和 源代码的错误位置
* hidden-source-map(防止源代码泄露):外联
* 1.将生成的一个 source-map文件放在单独的 .map文件中
* 错误提示:错误代码错误原因,但是没有错误位置,
* 不能追踪源代码错误,只能提示到构建后代码的错误位置
* eval-source-map:内联
* 1.针对每一个文件都生成一个单独的 source-map文件,放在 .js文件的 eval函数中
* 错误提示:错误代码准确信息 和 源代码的错误位置
* nosource-source-map(防止源代码泄露):外联
* 错误提示:错误代码准确信息, 但是没有任何源代码信息(可以防止源代码泄露)
* cheap-source-map:外联
* 错误提示:错误代码准确信息 和 源代码的错误位置,只能精确到行
* cheap-module-source-map:外联
* 错误提示:错误代码准确信息 和 源代码的错误位置,
* module会将 loader的 source-map加入
*
*/
// 开启构建后代码与源码的映射
devtool: 'eval-source-map' // development
// devtool: 'source-map' // production
};
- 运行指令:webpack
externals
防止将一些第三方包,打包到最终的输出中 bundles,如 jQuery,我们希望通过 cdn引入进来,而不参与打包
- 修改配置文件
// webpack.config.js
mode: 'production',
// mode: 'development',
/**
* externals:
* 添加不被打包的第三方库
*/
externals: {
// 忽略的库名 -> npm包名
jquery: 'jQuery'
},
devServer: {
contentBase: resolve(__dirname, 'build'),
compress: true,
port: 3030,
open: true,
// 开启 HRM功能
hot: true,
},