调整项目
项目结构:
src/index.js
import _ from 'lodash'
import $ from 'jquery'
const dom = $('<div>')
dom.html(_.join(['yang', 'yue', 'dingli'], ' '))
$('body').append(dom)
webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
module.exports = {
entry: {
app: './src/index.js',
// lodash: './src/lodash.js'
},
output: {
filename: '[name].bundle.js', //入口文件走这里
chunkFilename: '[name].chunk.js', // 间接生成的文件走这里
path: path.resolve(__dirname, '../dist'),
//publicPath也会在服务器脚本用到,确保资源能够在 http://localhost:3000下正确访问
// publicPath: '/' //在正常没有启用web服务器时记得去掉
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new CleanWebpackPlugin(), //不需要修改
],
//代码分割: webpack在处理公用内库的时候,会自动把库打包成单独一个文件,业务逻辑再打包成一个文件
optimization: {
//在使用MiniCssExtractPlugin时,从dev放到这里
usedExports: true,
// 1.splitChunks : 参考链接: https://www.webpackjs.com/plugins/split-chunks-plugin/
splitChunks: {
chunks: 'all',
//添加的配置项
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
filename: 'vendors.js'
},
}
},
}
}
webpack.prod.js
const commonConfig = require('./webpack.common.js')
const merge = require('webpack-merge')
const MiniCssExtractPlugin = require("mini-css-extract-plugin") //生产环境下使用
const prodConfig = {
mode: 'production', //有Tree Shaking功能,不需要配置项,但要修改devtool: cheap-module-source-map
// devtool: 'cheap-module-source-map',
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css', //直接被页面引用走这里
chunkFilename: '[name].chunk.css'
})
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader', //babel-loader:babel和webpack中间的桥梁
options: {
"presets": [
[
//es6=>es5
"@babel/preset-env", {
"targets": {
// "edge": "17",
// "firefox": "60",
// "chrome": "67",
"safari": "11.1", //以上版本已经支持es6,不需要再做es6=>es5
},
"corejs": '2', //解决警告: We noticed you're using the `useBuiltIns` option without declaring a core-js version
useBuiltIns: 'usage'
}
],
"@babel/preset-react", //转化react代码
],
// plugins: ["dynamic-import-webpack"] //用于异步模块代码分割,该插件不支持魔法注释,在添加注释时应到package.json中删除它
plugins: ["@babel/plugin-syntax-dynamic-import"] //使用官方插件,参考链接: https://www.babeljs.cn/docs/babel-plugin-syntax-dynamic-import
}
},
{
test:/\.css$/,
use: [
// 'style-loader',
MiniCssExtractPlugin.loader, //要使用插件提供的loader 替换掉style-loader //然后打包生成线上代码npm run build
'css-loader'
]
},
]
},
}
module.exports = merge(commonConfig, prodConfig)
webpack.dev.js
const webpack = require('webpack')
const merge = require('webpack-merge') //先安装: npm i webpack-merge --save-dev
const commonConfig = require('./webpack.common.js')
const devConfig = {
mode: 'development', //默认没有Tree Shaking功能, devtool: cheap-module-eval-source-map
devtool: 'cheap-module-eval-source-map',
devServer: {
contentBase: './dist',
open: true,
port: 8080,
hot: true,
// hotOnly: true //去掉后更改会自动刷新页面
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader', //babel-loader:babel和webpack中间的桥梁
options: {
"presets": [
[
//es6=>es5
"@babel/preset-env", {
"targets": {
// "edge": "17",
// "firefox": "60",
// "chrome": "67",
"safari": "11.1", //以上版本已经支持es6,不需要再做es6=>es5
},
"corejs": '2', //解决警告: We noticed you're using the `useBuiltIns` option without declaring a core-js version
useBuiltIns: 'usage'
}
],
"@babel/preset-react", //转化react代码
],
// plugins: ["dynamic-import-webpack"] //用于异步模块代码分割,该插件不支持魔法注释,在添加注释时应到package.json中删除它
plugins: ["@babel/plugin-syntax-dynamic-import"] //使用官方插件,参考链接: https://www.babeljs.cn/docs/babel-plugin-syntax-dynamic-import
}
},
{
test:/\.css$/,
use: [
'style-loader',
'css-loader'
]
},
]
},
plugins: [
new webpack.HotModuleReplacementPlugin() //要先引入webpack,是webpack自带的插件
],
//Tree Shaking配置项
//在使用MiniCssExtractPlugin时,引入css文件没有使用没有输出,会被摇晃树摇晃掉,需要在package.json配置sideEffects
// optimization: {
// usedExports: true
// }
}
module.exports = merge(commonConfig, devConfig)
运行npm run build
,生成打包文件:
contenthash
因为第一次访问,浏览器会缓存资源,而如果修改了页面内容再次访问时,存在缓存中的文件名没有变,则拿到的依然是缓存中的资源,导致出错
解决办法: 引入contenthash
webpack.common.js
output: {
path: path.resolve(__dirname, '../dist'),
},
//...
splitChunks: {
chunks: 'all',
//添加的配置项
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
// filename: 'vendors.js'
},
}
},
webpack.dev.js
output: {
filename: '[name].js', //入口文件走这里
chunkFilename: '[name].js', // 间接生成的文件走这里
},
webpack.prod.js
//[contenthash] 内容改变值就改变
output: {
filename: '[name].[contenthash].js', //入口文件走这里
chunkFilename: '[name].[contenthash].js', // 间接生成的文件走这里
},
再次打包npm run build
:
修改index.js中内容,再次打包npm run build
:
业务代码变化,对应的hash值跟着变化
而vendor中放置的是jquery和lodash代码,没有改动, hash值不变
总结: 通过使用contenthash打包代码上线时, 只需要更新有变化的代码,没有变化的代码则用本地缓存