1 简介
webpack 是一个静态模块打包器。(v4.41)入口js文件(引入JQ、less等chunk块)-->less转为css/es6转为es5-->打包后输出为bundle。
1.1 五个核心概念
入口(Entry)
输出(Output)
Loader :让 webpack 去处理那些非 JavaScript 文件 (webpack 自 身 只 理 解 JavaScript)
插件(Plugins):可以用于执行范围更广的任务
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
/*
entry: 入口起点
1. string --> './src/index.js'
单入口:打包形成一个chunk, 输出一个bundle文件。
-->此时chunk的名称默认是 main
2. array --> ['./src/index.js', './src/add.js']
多入口:所有入口文件最终只会形成一个chunk, 输出一个bundle文件。
--> 只有在HMR功能中让html热更新生效~
3. object
多入口:有几个入口文件就形成几个chunk,输出几个bundle文件
-->此时chunk的名称是 key
*/
module.exports = {
entry: {
index: ['./src/index.js', './src/count.js'],
add: './src/add.js'
},
output: {
// 文件名称(指定名称+目录)---主文件
filename: 'js/[name].js',
// 输出文件目录(将来所有资源输出的公共目录)
path: resolve(__dirname, 'build'),
// 所有资源引入公共路径前缀 --> 'js/built.js' --> '/js/built.js'
publicPath: '/',
publicPath: 'http://cdn.abc.com' // 修改所有静态文件 url 的前缀(如 cdn 域名),这里暂时用不到
chunkFilename: 'js/[name]_chunk.js', // 非入口chunk的名称:0_chunk.js(import引入的方式)---chunk方式命名表示非主文件
//assetModuleFilename: "static/media/[name].[hash][ext]", // 图片、字体等资源命名方式(注意用hash)
// library: '[name]', // 整个库向外暴露的变量名main
// libraryTarget: 'window' // 变量名添加到哪个上 browser
// libraryTarget: 'global' // 变量名添加到哪个上 node
// libraryTarget: 'commonjs'
},
module: {
rules: [
// loader的配置
{
test: /\.css$/,
use: ['style-loader', 'css-loader']// 多个loader用use
},
{
test: /\.js$/,
exclude: /node_modules/,// 排除node_modules下的js文件
include: resolve(__dirname, 'src'),// 只检查 src 下的js文件
enforce: 'pre',// 优先执行;post延后执行
loader: 'eslint-loader',// 单个loader用loader
options: {}
},
{
// 以下配置只会生效一个
oneOf: []
}
]
},
plugins: [new HtmlWebpackPlugin()],
mode: 'development'
};
1.2 基本使用
npm install webpack webpack-cli -D
2 开发环境的基本配置
2.1 配置
打包样式资源:less-loader css-loader style-loader
打包html资源: html-webpack-plugin
处理图片资源:url-loader html-loader
处理其他资源:file-loader
devServer:webpack-dev-server
2.2 编码
/*
开发环境配置:能让代码运行
运行项目指令:
webpack 会将打包结果输出出去
npx webpack-dev-server 只会在内存中编译打包,没有输出
*/
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build')// 输出路径:__dirname代表当前文件的目录绝对路径
},
module: {
rules: [
// loader的配置
{
// 处理less资源
test: /\.less$/,// 匹配哪些文件
//less-loader:将less文件编译成css文件
//css-loader:将css文件变成commonjs模块加载js中
//style-loader:创建style标签,将js中的样式添加到head中生效
use: ['style-loader', 'css-loader', 'less-loader']// use数组中loader执行顺序:从右到左,从下到上依次执行
},
{
// 处理css资源
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
// 处理sass资源:安装sass-loader sass
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
// 处理stylus资源:安装stylus-loader
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
// 处理图片资源
test: /\.(jpg|png|gif)$/,
loader: 'url-loader',//依赖于file-loader
options: {
limit: 8 * 1024,// 图片大小小于8kb,就会被base64处理;减少请求数量,图片体积会更大
name: '[hash:10].[ext]',// [hash:10]取图片的hash的前10位 [ext]取文件原来扩展名
esModule: false,// 关闭es6模块化:因为url-loader默认使用es6模块化解析,而html-loader引入图片是commonjs
outputPath: 'imgs'
}
},
{
// 处理html中img资源
test: /\.html$/,
loader: 'html-loader'//引入图片,从而被url-loader处理
},
{
// 处理其他资源(如图标字体)
exclude: /\.(html|js|css|less|jpg|png|gif)/,
loader: 'file-loader',
options: {
name: '[hash:10].[ext]',
outputPath: 'media'
}
}
]
},
plugins: [
// plugins的配置
new HtmlWebpackPlugin({//默认会创建一个空的HTML,自动引入打包输出的所有资源(JS/CSS)
template: './src/index.html'// 复制 './src/index.html' 文件
})
],
mode: 'development',
devServer: {// 开发服务器 devServer:用来自动化(自动编译,自动打开浏览器,自动刷新浏览器~~)
contentBase: resolve(__dirname, 'build'),// 项目构建后路径
watchContentBase: true,// 监视 contentBase 目录下的所有文件,一旦文件变化就会 reload
watchOptions: {
ignored: /node_modules/ // 忽略文件
},
compress: true,// 启动gzip压缩
host: 'localhost',// 域名
port: 3000,
open: true// 自动打开浏览器
hot: true,// 开启HMR功能
clientLogLevel: 'none',// 不要显示启动服务器日志信息
quiet: true,// 除了一些基本启动信息以外,其他内容都不要显示
overlay: false,// 如果出错了,不要全屏提示~
proxy: {// 服务器代理 --> 解决开发环境跨域问题
// 一旦devServer(5000)服务器接受到 /api/xxx 的请求,就会把请求转发到另外一个服务器(3000)
'/api': {
target: 'http://localhost:3000',
// 发送请求时,请求路径重写:将 /api/xxx --> /xxx (去掉/api)
pathRewrite: {
'^/api': ''
}
}
}
},
resolve: {// 解析模块的规则
// 配置解析模块路径别名: 优点简写路径 缺点路径没有提示
alias: {
$css: resolve(__dirname, 'src/css')
},
// 配置省略文件路径的后缀名
extensions: ['.js', '.json', '.jsx', '.css'],
// 告诉 webpack 解析模块是去找哪个目录(node_modules)
modules: [resolve(__dirname, '../../node_modules'), 'node_modules']
}
};
3 生产环境的基本配置
3.1 配置
提取css为单独文件:min-css-extract-plugin
- Css 文件目前被打包到 js 文件中,当 js 文件加载时,会创建一个 style 标签来生成样式。这样对于网站来说,会出现闪屏现象。
- 我们应该是单独的 Css 文件,通过 link 标签加载性能才好。
css兼容性处理:postcss-loader postcss-preset-env postcss
压缩css:optimize-css-assets-webpack-plugin
js语法检查:eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import
js兼容性处理:
babel-loader @babel/core @babel/preset-env(基本语法)core-js(高级语法按需加载)
@babel/polyfill:promise可以,兼容性代码全部引入,体积太大。入口文件直接引入
压缩html: html-webpack-plugin
3.2 编码
const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 定义nodejs环境变量:决定使用browserslist的哪个环境,默认为生产环境
process.env.NODE_ENV = 'production';
// 复用loader
/*
"browserslist": {
// 开发环境 --> 设置node环境变量:process.env.NODE_ENV = development
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
// 生产环境:默认是看生产环境
"production": [
">0.2%",
"not dead",
"not op_mini all"
]
}
*/
const commonCssLoader = [
MiniCssExtractPlugin.loader,// 这个loader取代style-loader。作用:提取js中的css成单独文件。最终通过link引入,减小js文件的体积,还可以避免闪屏
'css-loader',
{
// 还需要在package.json中定义browserslist
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [require('postcss-preset-env')()]//帮postcss找到package.json中browserslist里面的配置,通过配置加载指定的css兼容性样式
}
}
];
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build')
},
module: {
rules: [
{
test: /\.css$/,
use: [...commonCssLoader]
},
{
test: /\.less$/,
use: [...commonCssLoader, 'less-loader']
},
/*
1.正常来讲,一个文件只能被一个loader处理。当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序:先执行eslint 在执行babel。
2.在package.json中eslintConfig设置检查规则 --> airbnb--> eslint-config-airbnb-base eslint-plugin-import eslint
"eslintConfig": {
"extends": "airbnb-base"
}
*/
{//js语法检查
test: /\.js$/,
exclude: /node_modules/,//只检查自己写的源代码
enforce: 'pre',// 优先执行
loader: 'eslint-loader',//依赖于eslint
options: {
fix: true// 自动修复eslint的错误
}
},
{//js兼容性处理
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',//依赖于@babel/core
options: {
presets: [
[
'@babel/preset-env',//基本js兼容性处理
{
useBuiltIns: 'usage',// 按需加载
corejs: {version: 3},// 指定core-js版本
targets: {// 指定兼容性做到哪个版本浏览器
chrome: '60',
firefox: '50',
ie: '9',
safari: '10',
edge: '17'
}
}
]
],
cacheCompression: false, // 缓存文件不要压缩
cacheDirectory: true// 开启babel缓存。第二次构建时,会读取之前的缓存
}
},
{
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
outputPath: 'imgs',
esModule: false
}
},
{
test: /\.html$/,
loader: 'html-loader'
},
{
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
outputPath: 'media'
}
}
]
},
plugins: [
new MiniCssExtractPlugin({//提取css为单独文件
filename: 'css/built.css',
chunkFilename: "static/css/[name].chunk.css",
}),
new OptimizeCssAssetsWebpackPlugin(),// 压缩css
new HtmlWebpackPlugin({// 压缩html代码
template: './src/index.html',
minify: {
collapseWhitespace: true,// 移除空格
removeComments: true// 移除注释
}
})
],
mode: 'production'// 压缩js
optimization: {
splitChunks: {
chunks: 'all'
// 以下注释部分为默认值,可以不写~
/* minSize: 30 * 1024, // 分割的chunk最小为30kb
maxSiza: 0, // 最大没有限制
minChunks: 1, // 要提取的chunk最少被引用1次
maxAsyncRequests: 5, // 按需加载时并行加载的文件的最大数量
maxInitialRequests: 3, // 入口js文件最大并行请求数量
automaticNameDelimiter: '~', // 名称连接符
name: true, // 可以使用命名规则
cacheGroups: {
// 分割chunk的组
// node_modules文件会被打包到 vendors 组的chunk中。--> vendors~xxx.js
// 满足上面的公共规则,如:大小超过30kb,至少被引用一次。
vendors: {
test: /[\\/]node_modules[\\/]/,
// 优先级
priority: -10
},
default: {
// 要提取的chunk最少被引用2次
minChunks: 2,
// 优先级
priority: -20,
// 如果当前要打包的模块,和之前已经被提取的模块是同一个,就会复用,而不是重新打包模块
reuseExistingChunk: true
}
}*/
// 缓存分组
cacheGroups: {
// 第三方模块
vendor: {
name: 'vendor', // chunk 名称
priority: 1, // 权限更高,优先抽离,重要!!!
test: /node_modules/,
minSize: 0, // 大小限制
minChunks: 1 // 最少复用过几次
},
// 公共的模块
common: {
name: 'common', // chunk 名称
priority: 0, // 优先级
minSize: 0, // 公共模块的大小限制
minChunks: 2 // 公共模块最少复用过几次
}
}
},
// 问题:修改a文件导致b文件(import导入a文件)的contenthash变化,打包生成a和b(包含a文件名的映射关系)
runtimeChunk: {// 将当前模块的记录其他模块的hash单独打包为一个文件 runtime
name: entrypoint => `runtime-${entrypoint.name}`//打包后生成b/a/a_runtime文件
},
minimizer: [// 配置生产环境的压缩方案:js和css
new TerserWebpackPlugin({
// 开启缓存
cache: true,
// 开启多进程打包
parallel: true,
// 启动source-map
sourceMap: true
})
]
}
};
3.3 配置合并
const webpackCommonConf = require('./webpack.common.js')
const { smart } = require('webpack-merge')
module.exports = smart(webpackCommonConf, {
mode: 'development',
}
})
4 性能优化
开发:打包速度HMR、代码调试sourceMap
生产:打包速度oneOf、babel缓存、多进程打包、externals、dll、
代码性能:文件资源缓存、tree shaking、code split、懒加载、pwa
4.1 开发环境
HMR: hot module replacement 热模块替换 / 模块热替换
问题:npx xxx 启动开发环境配置--->修改代码,整个页面会重新刷新
作用:devServer中开启hot--->一个模块发生变化,只会重新打包这一个模块
/*
样式文件:可以使用HMR功能:因为style-loader内部实现了~
js文件:默认不能使用HMR功能 --> 修改index.js中的代码,根据hot属性存在,监听模块文件变化更新
注意:HMR功能只能处理非入口js文件 。
html文件: 默认不能使用HMR功能,同时会导致问题:html文件不能热更新了~ (不用做HMR功能)
解决:修改entry入口,将html文件引入
*/
const { resolve } = require('path');
module.exports = {
entry: ['./src/js/index.js', './src/index.html'],
output: {},
module: {},
plugins: [],
mode: 'development',
devServer: {
contentBase: resolve(__dirname, 'build'),
compress: true,
port: 3000,
open: true,
// 开启HMR功能
// 当修改了webpack配置,新配置要想生效,必须重新webpack服务
hot: true
}
};
index.js
if (module.hot) {
module.hot.accept('./print.js', function() {
// 方法会监听 print.js 文件的变化,一旦发生变化,其他模块不会重新打包构建。
// 会执行后面的回调函数
print();
});
}
source-map: 一种提供源代码到构建后代码映射技术,打包后生成js.map文件,快速定位源代码的错误位置。
开发环境:速度快,调试好 eval-source-map(内联)
生产环境:源代码隐藏,调试友好 source-map(外部js.map)
const { resolve } = require('path');
module.exports = {
entry: ['./src/js/index.js', './src/index.html'],
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build')
},
module: {
rules: []
},
plugins: [],
mode: 'development',
devServer: {},
devtool: 'eval-source-map'//source-map
};
4.2 生产环境
module中配置oneOf:同类型的文件只匹配一个loader,将eslint-loader提取出去。
const { resolve } = require('path');
// 复用loader
const commonCssLoader = [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [require('postcss-preset-env')()]
}
}
];
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
// 优先执行
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true
}
},
{
// 以下loader只会匹配一个
// 注意:不能有两个配置处理同一种类型文件
oneOf: [
{
test: /\.css$/,
use: [...commonCssLoader]
},
{
test: /\.less$/,
use: [...commonCssLoader, 'less-loader']
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: {version: 3},
targets: {
chrome: '60',
firefox: '50'
}
}
]
]
}
},
]
}
]
},
plugins: [],
mode: 'production'
};
babel缓存(第二次构建读取缓存)
文件资源缓存(上线):server.js用express搭建服务器引入built静态资源-->被强制缓存
hash: 每次wepack构建时会生成一个唯一的hash值。
问题: 因为js和css同时使用一个hash值。如果重新打包,会导致所有缓存失效 (只改动一个文件)
chunkhash:根据chunk生成的hash值。如果打包来源于同一个chunk,那么hash值就一样
问题: js和css的hash值还是一样的。因为css是在js中被引入的,所以同属于一个chunk
contenthash: 根据文件的内容生成hash值。不同文件hash值一定不一样
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.[contenthash:10].js',//js
path: resolve(__dirname, 'build')
},
module: {},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/built.[contenthash:10].css'//css
}),
],
mode: 'production',
};
tree shaking:去除无用代码,减少代码体积
前提:1. 必须使用ES6模块化 2. 开启production环境
code split:将打包生成的文件进行代码分割,生成多个 js 文件,渲染哪个页面就只加载某个 js 文件,这样加载的资源就少,速度就更快。代码分割(Code Split)主要做了两件事:
- 分割文件:将打包生成的文件进行分割,生成多个 js 文件。
- 按需加载:需要哪个文件就加载哪个文件。
a.入口文件有几个,就生成几个bundle;(多入口)b.配置了optimization中的chunks,将node_modules中代码单独打包一个chunk输出一个bundle;(第三方包:提取重复代码)c.import动态导入语法:能将某个文件单独打包成一个chunk。(源代码:按需加载,动态导入)
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
//方式一:
module.exports = {
// 单入口:输出一个bundle
// entry: './src/js/index.js',
entry: {
// 多入口:输出两个bundle
index: './src/js/index.js',
test: './src/js/test.js'
},
output: {
// [name]:取文件名
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname, 'build')
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
minify: {
collapseWhitespace: true,
removeComments: true
}
})
],
mode: 'production'
};
//方式二:
module.exports = {
// 单入口:输出两个个bundle
// entry: './src/js/index.js',//引入JQ
entry: {
// 多入口:输出三个bundle
index: './src/js/index.js',//引入JQ
test: './src/js/test.js'//引入JQ
},
output: {
// [name]:取文件名
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname, 'build')
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
minify: {
collapseWhitespace: true,
removeComments: true
}
})
],
/*
1. 可以将node_modules中代码单独打包一个chunk最终输出
2. 自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独一个chunk
*/
optimization: {
splitChunks: {
chunks: 'all'
}
},
mode: 'production'
};
//方式三:
//在方式二的基础上,在入口文件中引入test.js
/*
通过js代码,让某个文件被单独打包成一个chunk
import动态导入语法:能将某个文件单独打包
*/
// eslint会对动态导入语法报错,需要修改eslint配置文件
// webpackChunkName: "test":这是webpack动态导入模块命名的方式,配合output中的chunkFileName使用
// "test"将来就会作为[name]的值显示。
import(/* webpackChunkName: 'test' */'./test')
.then(({ mul, count }) => {
// 文件加载成功~
console.log(mul(2, 5));
})
.catch(() => {
console.log('文件加载失败~');
});
懒加载:当文件需要使用时才加载~
预加载:文件使用之前提前加载,其他资源加载完毕,浏览器空闲时加载。兼容性较差
Preload
:告诉浏览器立即加载资源,兼容性较好。Prefetch
:告诉浏览器在空闲时才开始加载资源。
Preload
加载优先级高,Prefetch
加载优先级低。Preload
只能加载当前页面需要使用的资源,Prefetch
可以加载当前页面资源,也可以加载下一个页面需要使用的资源。
document.getElementById('btn').onclick = function() {//点击按钮的时候加载index.js中的test.js
//预加载:webpackPrefetch: true
import(/* webpackChunkName: 'test', webpackPrefetch: true */'./test').then(({ mul }) => {
console.log(mul(4, 5));
});
};
PWA: 渐进式网络开发应用程序(离线可访问)
1.安装workbox-webpack-plugin,打包后会生成service-worker.js文件
2.入口文件注册配置文件,需要修改eslintConfig配置来支持浏览器全局变量
3.将build文件夹下静态文件通过服务器暴露出去
const { resolve } = require('path');
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
/*
PWA: 渐进式网络开发应用程序(离线可访问)
workbox --> workbox-webpack-plugin
*/
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.[contenthash:10].js',
path: resolve(__dirname, 'build')
},
module: { },
plugins: [
new WorkboxWebpackPlugin.GenerateSW({
/*
1. 帮助serviceworker快速启动
2. 删除旧的 serviceworker
生成一个 serviceworker 配置文件~
*/
clientsClaim: true,
skipWaiting: true
})
],
mode: 'production',
};
/*
1. eslint不认识 window、navigator全局变量
解决:需要修改package.json中eslintConfig配置
"env": {
"browser": true // 支持浏览器端全局变量
}
2. sw代码必须运行在服务器上
--> nodejs
-->
npm i serve -g
serve -s build 启动服务器,将build目录下所有资源作为静态资源暴露出去
*/
// index.js中注册serviceWorker
// 处理兼容性问题
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker
.register('/service-worker.js')
.then(() => {
console.log('sw注册成功了~');
})
.catch(() => {
console.log('sw注册失败了~');
});
});
}
开启多进程打包:开启电脑的多个进程同时干一件事。我们想要继续提升打包速度,其实就是要提升 js 的打包速度,而对 js 文件处理主要就是 eslint 、babel、Terser 三个工具。
我们启动进程的数量就是我们 CPU 的核数。每个进程启动大概为600ms,进程通信也有开销,不要滥用。
const { resolve } = require('path');
const os = require("os");// nodejs核心模块,直接使用
const threads = os.cpus().length;//cpu核数
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.[contenthash:10].js',
path: resolve(__dirname, 'build')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'thread-loader',//配置thread-loader
options: {
workers: 2 // 进程2个
}
},
{
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: { version: 3 },
targets: {
chrome: '60',
firefox: '50'
}
}
]
],
cacheDirectory: true
}
}
]
},
]
},
plugins: [],
mode: 'production',
};
externals:配置忽略的库名,如JQ;此时JQ需要在html文件中通过CDN引入
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build')
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
mode: 'production',
externals: {
jquery: 'jQuery'// 拒绝jQuery被打包进来
}
};
使用dll技术,对某些库(第三方库:jquery、react、vue...)进行单独打包
webpack.dll.js
执行命令webpack --config webpack.dll.js
结果生成了jQuery.js和manifest.json文件,manifest用来提供和JQ映射
/*
当你运行 webpack 时,默认查找 webpack.config.js 配置文件
需求:需要运行 webpack.dll.js 文件
--> webpack --config webpack.dll.js
*/
const { resolve } = require('path');
const webpack = require('webpack');
module.exports = {
entry: {
// 最终打包生成的[name] --> jquery
// ['jquery'] --> 要打包的库是jquery
jquery: ['jquery'],
},
output: {
filename: '[name].js',
path: resolve(__dirname, 'dll'),
library: '[name]_[hash]' // 打包的库里面向外暴露出去的内容叫什么名字
},
plugins: [
// 打包生成一个 manifest.json --> 提供和jquery映射
new webpack.DllPlugin({
name: '[name]_[hash]', // 映射库的暴露的内容名称
path: resolve(__dirname, 'dll/manifest.json') // 输出文件路径
})
],
mode: 'production'
};
webpack.config.js
1.引入manifest.json文件,不再打包jq(jq部署到自己服务器上)
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build')
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
// 告诉webpack哪些库不参与打包,同时使用时的名称也得变~
new webpack.DllReferencePlugin({
manifest: resolve(__dirname, 'dll/manifest.json')
}),
// 将某个文件打包输出去,并在html中自动引入该资源
new AddAssetHtmlWebpackPlugin({
filepath: resolve(__dirname, 'dll/jquery.js')
})
],
mode: 'production'
};