$ npm init -y
package.json
$ npm install webpack webpack-cli --save-dev
$ npm i webpack-dev-server --save-dev
创建 webpack.config.js 配置文件
$ npm i html-loader html-webpack-plugin --save-dev
.
├── public
│ └── index.html ## html模版文件
├── src
│ ├── asset ## 资源文件
│ └── main.js ## webpack入口文件
├── package.json ## npm init
└── webpack.config.js ## webpack默认配置文件
const {
resolve} = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
/* 入口 */
entry: [
resolve(__dirname, 'src/main.js'),
],
/* 插件 */
plugins: [
/* 生成一个HTML文件作为站点入口 */
new HtmlWebpackPlugin({
template: resolve(__dirname, 'public/index.html'), // 模版html
}),
],
/* 模式 development || production */
mode: "development",
/* 开发环境服务 npx webpack-dev-server */
devServer: {
/* 内容地址 */
contentBase: resolve(__dirname, 'dist'),
/* 启动gzip压缩 */
compress: true,
/* 站点的端口号 */
port: 3000,
/* 执行后自动打开浏览器 */
open: true,
}
};
$ npm i style-loader css-loader less less-loader --save-dev
module.exports = {
/* 配置loader */
module: {
/* 规则配置 默认从数组尾向前进行处理 */
rules: [
/* 处理css文件 style-loader, css-loader */
{
test: /\.css$/, use: ['style-loader', 'css-loader']},
/* 处理less文件 style-loader, css-loader, less-loader */
{
test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader']},
],
}
}
$ npm i clean-webpack-plugin --save-dev
const {
CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
plugins: [
/* 每次构建清空打包后目录文件夹 */
new CleanWebpackPlugin(),
]
}
entry : String
--> 单入口模式 (打包会生成一个chunk,输出一个bundle文件)
module.exports = {
entry: './src/main.js'
}
entry : Array
--> 多入口模式 (所有入口文件最终只会形成一个chunk,输出一个bundle文件)
一般会将html文件放入,使开发环境的HMR配置生效
module.exports = {
entry: [ './src/main.js', './public/index.html', ],
}
entry : Object
--> 多入口模式 (有几个入口文件最终就会形成几个chunk,chunk名称为key,同时也会输出几个bundle文件)
module.exports = {
entry: {
main: './src/main.js',
demo: './src/views/demo.js',
}
}
entry : Object[Array]
--> 多入口模式 (数组部分打包成一个chunk,字符串部分打包成一个chunk)
module.exports = {
entry: {
main: [ './src/main.js', './src/views/index.js' ],
demo: './src/views/demo.js',
}
}
module.exports = {
/* 出口 */
output: {
/* 构建输出地址 绝对路径 */
path: resolve(__dirname, 'dist'),
/* 构建输出文件名称 注意:配置热更新hot后启动服务将无法使用contenthash作为文件名 */
filename: this.mode === 'production' ? 'js/[name].[contenthash:10].js' : 'js/[name].[hash:10].js',
/* 输出文件路径定义 一般用于生产环境 */
publicPath: '/',
/* 对非入口文件chunk创建名称 js代码采用import('./xxx/xxx.js').then().catch(); */
chunkFilename: 'js/[name]_chunk.js',
/* 将value作为打包后的全局变量暴露出来,默认用var定义 示例:var main = (function(modules) {···})({···}) */
library: '[name]',
/* 设置后默认值 var , 实现通过哪种(var, commonjs, window, global)方式定义暴露的变量 */
libraryTarget: 'var', // var commonjs window global
},
}
module.exports = {
/* 配置loader */
module: {
/* loader配置 默认从数组尾向前进行处理 */
rules: [
/* 处理css文件 style-loader, css-loader */
{
test: /\.css$/, use: ['style-loader', 'css-loader']},
/* 处理less文件 style-loader, css-loader, less-loader */
{
test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader']},
/* 处理html文件 html-loader 将 HTML 导出为字符串。当编译器需要时,将压缩 HTML 字符串 */
{
test: /\.html$/, loader: 'html-loader'},
],
},
}
import '../../../../xxx/xxx/xxx.css';
/* main.js */
import '$css/common.css';
import '$css/demo.less';
/* webpack.config.js */
module.exports = {
/* 解析模块的规则 */
resolve: {
/* 配置解析模块路径别名 */
alias: {
$css: resolve(__dirname, 'src/assets/css')
}
}
}
/* main.js */
import './css/xxx'; // 省略 .css
import './json/xxx'; // 省略 .json
import './js/xxx'; // 省略 .js
/* webpack.config.js */
module.exports = {
/* 解析模块的规则 */
resolve: {
/* 配置省略文件路径后缀名 (先会去查找.js文件,有就返回,没有继续向后查找) */
extensions: [ '.js', '.json', '.css']
}
}
module.exports = {
/* 解析模块的规则 */
resolve: {
/* 配置解析模块(node_modules)寻找地址 (默认在webpack.config.js所在目录向上寻找) */
modules: [ resolve(__dirname, 'node_modules'), 'node_modules' ], // 数组[1]预防之前配置寻找不到node_modules而配置
}
}
module.exports = {
/* npx webpack-dev-server */
devServer: {
/* 内容地址 */
contentBase: resolve(__dirname, 'dist'),
/* 监视 contentBase 下的所有文件,一旦文件产生变化就会reload刷新 */
watchContentBase: true,
/* 监视配置 */
watchOptions: {
/* 忽略 node_modules 下文件 */
ignored: /node_modules/
},
/* 启动gzip压缩 */
compress: true,
/* 站点的端口号 */
port: 3000,
/* 域名 */
host: 'localhost',
/* 执行后自动打开浏览器 */
open: true,
/* 热更新 */
hot: true,
/* 不需要打印启动程序时的日志信息 */
clientLogLevel: false,
/* 除了一些基本启动信息以外,其他内容不需要打印 */
quiet: true,
/* 如果出错了,不需要全屏提示 */
overlay: false,
/* 服务器代理 --> 解决开发环境跨域问题 */
proxy: {
/* 接收到/api/xxx的请求后,会将请求转发到http://localhost:3000这个地址下,从而解决跨域 */
'/api': {
target: 'http://localhost:3000',
/* 路径重写 将请求路径 /api/xxx 改写成 /xxx (去掉 /api ) */
pathRewrite: {
'^/api': ''
}
}
}
},
}
module.exports = {
mode: 'production',
/* 优化 mode: 'production' */
optimization: {
/* chunk分割 */
splitChunks: {
chunks: 'all',
/* ========================以下为默认配置项,可以不写========================= */
/* 分割的chunk最小为30kb */
minSize: 30 * 1024,
/* 分割的chunk最大无限制 */
maxSize: 0,
/* 提取的chunk最少被引用1次 */
minChunks: 1,
/* 按需加载时并行加载的文件最大数量 */
maxAsyncRequests: 5,
/* 入口js文件最大并行请求数量 */
maxInitialRequests: 3,
/* 名称连接符 */
automaticNameDelimiter: '~',
/* 可以使用命名规则 */
name: true,
/* 分割chunk的组 */
cacheGroups: {
/* node_modules中的文件会被打包到vendors组的chunk中, 名称:vendors~xxx.js */
vendors: {
test: /[\\/]node_modules[\\/]/,
/* 优先级 */
priority: -10,
},
default: {
/* 提取的chunk最少被引用2次 */
minChunks: 2,
priority: -20,
/* 如果当前要打包的模块和之前已经被提取的模块是同一个,就会复用,而不是重新打包模块,比如都引入了jQuery */
reuseExistingChunk: true,
}
}
}
}
}
// main.js
import(/* webpackChunkName: 'index' */ './views/index')
.then(res=>{
console.log(res);
})
.catch(err=>{
console.log(err);
});
// index.js
console.log('Index Js');
// => 修改为
// console.log('Index Js ABC');
// webpack.config.js
module.exports = {
mode: 'production',
/* 优化 mode: 'production' */
optimization: {
/* chunk分割 */
splitChunks: {
chunks: 'all',
}
}
}
当其中index.js的代码进行修改后,
预期希望打包后只有index.js的文件名发生变化,不会影响到main.js的缓存机制,
但是由于main.js代码内部存储了index.js文件的hash值,
最终导致index.js被修改后再次打包main.js和index.js的文件名都发生了变化,
导致main.js文件没有从缓存中读取,又请求了一次,影响性能
希望提取出main.js中引用的index.js的hash值在进行单独处理
// webpack.config.js
module.exports = {
mode: 'production',
/* 优化 mode: 'production' */
optimization: {
/* chunk分割 */
splitChunks: {
chunks: 'all',
}
},
/* 将当前模块记录的其他模块的hash值单独打包成一个文件 runtime */
runtimeChunk: {
name: entrypoint => `runtime-${
entrypoint.name}`
}
}
$ npm i terser-webpack-plugin --save-dev
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
optimization: {
/* 配置生产环境的压缩方案 js和css方案 */
minimizer: [
new TerserPlugin({
/* 开启缓存 */
cache: true,
/* 开启多进程打包 */
parallel: true,
/* 启用 source-map */
sourceMap: true,
}),
]
}
}
npm i html-loader --save-dev
npm i terser-webpack-plugin --save-dev
npm i clean-webpack-plugin --save-dev
npm i style-loader css-loader less less-loader --save-dev
npm i html-webpack-plugin --save-dev
npm i webpack-dev-server --save-dev
npm i webpack webpack-cli --save-dev
{
"name": "javascriptdesignpatterns",
"version": "1.0.0",
"description": "设计模式",
"main": "index.js",
"scripts": {
"dev": "npx webpack-dev-server",
"build": "webpack"
},
"author": "ProsperLee",
"license": "ISC",
"devDependencies": {
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^4.3.0",
"html-loader": "^1.3.2",
"html-webpack-plugin": "^4.5.0",
"less": "^3.12.2",
"less-loader": "^7.0.2",
"style-loader": "^2.0.0",
"terser-webpack-plugin": "^4.2.3",
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0"
}
}
// webpack.config.js
const {
resolve} = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {
CleanWebpackPlugin } = require('clean-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
/* 入口 */
entry: [
'./src/main.js',
'./public/index.html',
],
/* 出口 */
output: {
/* 构建输出地址 绝对路径 */
path: resolve(__dirname, 'dist'),
/* 构建输出文件名称 注意:配置热更新hot后启动服务将无法使用contenthash作为文件名 */
filename: this.mode === 'production' ? 'js/[name].[contenthash:10].js' : 'js/[name].[hash:10].js',
/* 输出文件路径定义 一般用于生产环境 */
publicPath: '/',
/* 对非入口文件chunk创建名称 */
chunkFilename: 'js/[name].[contenthash:10]_chunk.js',
/* 将value作为打包后的全局变量暴露出来,默认用var定义 示例:var main = (function(modules) {···})({···}) */
library: '[name]',
/* 设置后默认值 var , 实现通过哪种(var, commonjs, window, global)方式定义暴露的变量 */
libraryTarget: 'var', // var commonjs window global
},
/* 配置loader */
module: {
/* loader配置 默认从数组尾向前进行处理 */
rules: [
/* 处理css文件 style-loader, css-loader */
{
test: /\.css$/, use: ['style-loader', 'css-loader']},
/* 处理less文件 style-loader, css-loader, less-loader */
{
test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader']},
/* 处理html文件 html-loader 将 HTML 导出为字符串。当编译器需要时,将压缩 HTML 字符串 */
{
test: /\.html$/, loader: 'html-loader'},
],
},
/* 插件 */
plugins: [
/* 每次构建清空打包后目录文件夹 */
new CleanWebpackPlugin(),
/* 生成一个HTML文件作为站点入口 */
new HtmlWebpackPlugin({
template: resolve(__dirname, 'public/index.html'), // 模版html
minify: true, // 是否压缩
}),
],
/* 模式 development || production */
mode: 'development',
/* npx webpack-dev-server */
devServer: {
/* 内容地址 */
contentBase: resolve(__dirname, 'dist'),
/* 监视 contentBase 下的所有文件,一旦文件产生变化就会reload刷新 */
watchContentBase: true,
/* 监视配置 */
watchOptions: {
/* 忽略 node_modules 下文件 */
ignored: /node_modules/
},
/* 启动gzip压缩 */
compress: true,
/* 站点的端口号 */
port: 3000,
/* 域名 */
host: 'localhost',
/* 执行后自动打开浏览器 */
open: true,
/* 热更新 */
hot: true,
/* 不需要打印启动程序时的日志信息 */
clientLogLevel: false,
/* 除了一些基本启动信息以外,其他内容不需要打印 */
quiet: true,
/* 如果出错了,不需要全屏提示 */
overlay: false,
/* 服务器代理 --> 解决开发环境跨域问题 */
proxy: {
/* 接收到/api/xxx的请求后,会将请求转发到http://localhost:3000这个地址下,从而解决跨域 */
'/api': {
target: 'http://localhost:3000',
/* 路径重写 将请求路径 /api/xxx 改写成 /xxx (去掉 /api ) */
pathRewrite: {
'^/api': ''
}
}
}
},
/* 开启调试功能 */
devtool: 'eval-source-map',
/* 解析模块的规则 */
resolve: {
/* 配置解析模块路径别名 */
alias: {
$css: resolve(__dirname, 'src/assets/css')
},
/* 配置省略文件路径后缀名 (先会去查找.js文件,有就返回,没有继续向后查找) */
extensions: [ '.js', '.json', '.css'],
/* 配置解析模块(node_modules)寻找地址 (默认在webpack.config.js所在目录向上寻找) */
modules: [ resolve(__dirname, 'node_modules'), 'node_modules' ], // 数组[1]预防之前配置寻找不到node_modules而配置
},
/* 优化 mode: 'production' */
optimization: {
/* chunk分割 */
splitChunks: {
chunks: 'all',
// /* 分割的chunk最小为30kb */
// minSize: 30 * 1024,
// /* 分割的chunk最大无限制 */
// maxSize: 0,
// /* 提取的chunk最少被引用1次 */
// minChunks: 1,
// /* 按需加载时并行加载的文件最大数量 */
// maxAsyncRequests: 5,
// /* 入口js文件最大并行请求数量 */
// maxInitialRequests: 3,
// /* 名称连接符 */
// automaticNameDelimiter: '~',
// /* 可以使用命名规则 */
// name: true,
// /* 分割chunk的组 */
// cacheGroups: {
// /* node_modules中的文件会被打包到vendors组的chunk中, 名称:vendors~xxx.js */
// vendors: {
// test: /[\\/]node_modules[\\/]/,
// /* 优先级 */
// priority: -10,
// },
// default: {
// /* 提取的chunk最少被引用2次 */
// minChunks: 2,
// priority: -20,
// /* 如果当前要打包的模块和之前已经被提取的模块是同一个,就会复用,而不是重新打包模块,比如都引入了jQuery */
// reuseExistingChunk: true,
// }
// }
},
/* 将当前模块记录的其他模块的hash值单独打包成一个文件 runtime */
runtimeChunk: {
name: entrypoint => `runtime-${
entrypoint.name}`
},
/* 配置生产环境的压缩方案 js和css方案 */
minimizer: [
new TerserPlugin({
/* 开启缓存 */
cache: true,
/* 开启多进程打包 */
parallel: true,
/* 启用 source-map */
sourceMap: true,
}),
],
}
};