参考文档 webpack官网: https://webpack.docschina.org/concepts/
{
"name": "my-app", // 项目的名称 长度必须小于或等于214个字符,不能以“.”和“_”开头,不能包含大写字母
"version": "0.1.0", // 组成的标识是唯一的,改变包的时候应该同时改变 version
"private": true, // private字段可以防止我们意外地将私有库发布到npm服务器。
"main":"dist/index.js",// 文件的输出路径
"miniprogram": "dist/index.js", // 小程序包 输出路径
"dependencies": {}, // 项目描述
"keywords":"cli", // 字段段是一个字符串数组,表示这个项目包的关键词。和description一样,都是用来增加项目包的曝光率的
"bin":"lib/index.js", // 用来指定各个内部命令对应的可执行文件的位置
"author":"zsj",// 作者
"repository": "https://github.com/facebook/react.git",// 仓库地址
"scripts": { // 脚本配置
"start": "--env name=webpack --node-env development react-scripts start",
},
"devDependencies": { // 测试环境依赖包
"babel-core": "^6.22.1"
},
"dependencies": { //项目的生产环境中所必须的依赖包
"react": "^17.0.2",
},
"engines": { // npm包的版本或者Node版本有特殊要求
"node": ">=8.10.3 <12.13.0",
"npm": ">=6.9.0"
},
"eslintConfig": {},//eslint 配置
"browserslist": { //用来告知支持哪些浏览器及版本
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"license": "ISC" // license 字段用于指定软件的开源协议,开源协议表述了其他人获得代码后拥有的权利,可以对代码进行何种操作,何种操作又是被禁止的。
}
dependencies和devDependencies的区别
devDependencies
用字面来翻译就是“开发依赖”,就是一些在开发时候才会用到的工具包,例如:webpack,chalk,fs-extra,opn 等项目上线后不需依赖相关代码运行的工具。
dependencies
就是“依赖”,原则上来说这个字段的工具包只允许放生产环境中项目所使用的依赖,例如:Vue,React,axios 等相关代码缺失会导致项目运行错误的工具。
依赖混乱有什么后果?
什么是依赖混乱?依赖混乱就是将本应该在生产环境的包放进开发依赖,将开发环境的包放进生产依赖。
1. 生产环境的包放进开发依赖
具体就例如:将 Vue 放进 devDependencies,这样做的后果是什么?分两种情况:
● 下载项目源码,然后运行 npm install。这种情况无论 Vue 在哪个字段里都会被正确下载到 node_modules 里。
● 作为 npm 包发布,然后 npm install xxx 的形式下载。这种情况只会下载 dependencies 的依赖,其余依赖将会无视处理,这样别人下载你的 npm 包运行时,就会找不到 xxx 而出错。
2. 开发环境的包放进生产依赖
具体就例如:将 fs-extra jest 放进 dependencies,这样做的后果是什么?分两种情况:
● 下载项目源码,然后运行 npm install。这种情况无论 fs-extra jest 在哪个字段里都会被正确下载到 node_modules 里。
● 作为 npm 包发布,然后 npm install xxx 的形式下载。这种情况只会下载 dependencies 的依赖,其余依赖将会无视处理,这样别人下载你的 npm 包运行时,就会包含有 fs-extra jest 代码,从而增加本地项目的体积。
一般来说一个 chunk 对应一个 bundle,比如上图中的 utils.js -> chunks 1 -> utils.bundle.js;但也有例外,比如说上图中,我就用 MiniCssExtractPlugin 从 chunks 0 中抽离出了 index.bundle.css 文件。
**devtool**
```bash
source-map:外部,错误代码准确信息 和 源代码的错误位置
inline-source-map:内联,只生成一个内联 source-map,错误代码准确信息 和 源代码的错误位置
hidden-source-map:外部,错误代码错误原因,但是没有错误位置(为了隐藏源代码),不能追踪源代码错误,只能提示到构建后代码的错误位置
eval-source-map:内联,每一个文件都生成对应的 source-map,都在 eval 中,错误代码准确信息 和 源代码的错误位
nosources-source-map:外部,错误代码准确信息,但是没有任何源代码信息(为了隐藏源代码)
cheap-source-map:外部,错误代码准确信息 和 源代码的错误位置,只能把错误精确到整行,忽略列
cheap-module-source-map:外部,错误代码准确信息 和 源代码的错误位置,module 会加入 loader 的 source-map
## webpack 基本插件安装
```bash
1 cnpm i webpack webpack-cli webpack-dev-server -D
2 npm install -g npx
3 cnpm i babel-loader @babel/core @babel/runtime-corejs3 @babel/plugin-transform-runtime @babel/preset-env -D
4 cnpm i css-loader style-loader postcss-loader autoprefixer less less-loader -D
{
entry:'./src/index.js', // 入口文件
// ['./src/index.js','./src/a.js']
// {
// app : './src/index.js',
// index:'./src/a.js'
// }
output:{ // 出口
filename: "[name].[contenthash:8].js",
chunkFilename: 'js/[name].[contenthash:8]_chunk.js',
path: path.resolve(__dirname, '../dist'),
publicPath:"/",
assetModuleFilename: "img/[name].[hash:6][ext]", //webpack5 引用资源文件打包后的文件名
clean: true, //清除dist下文件
// library: "TEST", // 库暴露的变量名
// libraryTarget: "window",
},
devtool:"eval-cheap-module-source-map",
optimization: {
// 表示只导出那些外部使用了的模块
usedExports: true,
// 压缩模块
minimize: true,
minimizer: [
new TerserPlugin({
extractComments: false,//不将注释提取到单独的文件中 以及生成的txt 文件
}),
// css 压缩
// new OptimizeCssAssetsWebpackPlugin()
],
splitChunks: {
// 分割异步模块 all, async, initial (同步)
// all 表示同步和异步都会共享
// 主要将node_module 的代码单独打包成一个chunk 并输出
chunks: 'async',
minSize: 30000, // 字节 引入的文件大于30kb才进行分割
maxSize: 0, //50kb,尝试将大于50kb的文件拆分成n个50kb的文件
minChunks: 1, //模块至少使用次数
maxAsyncRequests: 5, //同时加载的模块数量最多是5个,只分割出同时引入的前5个文件
maxInitialRequests: 3, //首页加载的时候引入的文件最多3个
automaticNameDelimiter: '~', // 缓存组和生成文件名称之间的连接符
// automaticNameMaxLength: 30, // 抽离的名称最大长度
name: false, // 是否可以自由命名
cacheGroups: { //分割chunk的组
//自定义打包模块
vendors: {
// 先抽离第三方
test: /[\\/]node_modules[\\/]/,//正则匹配打包分离的文件条件
priority: -10, // //优先级,先打包到哪个组里面,值越大,优先级越高
filename: '[name].[hash:8].js',
},
default: { //默认打包模块 ,一般情况下打包业务模块编码。
minChunks: 2,
//一个模块可以属于多个缓存组。优化将优先考虑具有更高 priority(优先级)的缓存组。默认组的优先级为负,以允许自定义组获得更高的优先级(自定义组的默认值为 0)
priority: -20,
reuseExistingChunk: true, //模块嵌套引入时,判断是否复用已经被打包的模块
filename: 'conmon.js',
},
},
},
// 当前模块记录的其他模块的hash值单独打包成一个文件 b引用a 当a变化时 b 不会重新打包
runtimeChunk: {
name: (entrypoint) => `runtime-main_${entrypoint.name}`
}
},
module:{
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader',
},
{
test: /\.(css|less)$/i,
use: [
MiniCssExtractPlugin.loader ,
{
loader: 'css-loader',
options: {
importLoaders: 2, // importLoaders设置为1 会被postcss-loader给处理
// 2 就会被postcss-loader和less-loader给处理
},
},
'postcss-loader',
'less-loader',
]
},
{
test: /\.(jpe?g|png|gif)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 2 * 1024
}
},
generator: {
filename: 'img/[name].[hash:10].[ext]',
}
},
]
},
plugins:[
new webpack.DefinePlugin({
"process.env": isDev ? require('../dev.env') : require('../prod.env'),
}),
new HtmlWebpckPlugin({
template: './src/index.html', // 根据现有模板 在dist 文件下 生成模板
// 压缩html 控制以何种方式缩小输出
minify: {
collapseWhitespace: true, // 去掉空格
removeComments: true, // 移除注释
},
title: 'webpack',// 生成html标题
}),
new MiniCssExtractPlugin({
filename: 'assets/css/[name].[contenthash:8].css',
}),
new webpack.DllReferencePlugin({
context: __dirname,
manifest: path.resolve(__dirname, '../dll/manifest.json'),
}),
new AddAssetHtmlWebpackPlugin([{
filepath: path.resolve(__dirname, '../dll/main.dll.js'),
publicPath: "./" // 解决 引入路径 带‘auto’
}])
], //插件
mode:'development', //开发模式
// 解析配置
resolve: {
extensions: ['.js', '.ts', '.json', '.jsx', '.vue'], // 自动添加扩展名
alias: {
'@': path.join(__dirname, '../src')
}, // 告诉webpack 加载模块时 去哪个目录找
modules: ['node_modules'],
},
}
.babelrc
{
"presets": [
["@babel/preset-env", {
"modules": "auto",//将 ES6 module 转换为其他模块规范,可选 "adm" | "umd" | "systemjs" | "commonjs" | "cjs" | false,默认为 auto
"targets": {
"chrome": 52,
"firefox":"60",
"safari":"11.1",
"browsers": ["> 1%", "last 2 versions", "not ie <= 8", "safari 7"]
},
"useBuiltIns": "usage",
"corejs": "3"
}
]
],
"plugins": [
[ "@babel/plugin-transform-runtime", {
"corejs": 3
}
]
]
}
.postcss.config.js
module.exports = {
plugins: [
require("autoprefixer")({
overrideBrowserslist: [
"defaults",
"Android 4.1",
"iOS 7.1",
"Chrome>31",
"ff>31",
"ie>=8",
"last 2 versions",
">0%"
]
})
]
}
.browserslistrc
> 1% // 全球超过1%的人使用的浏览器,由全球使用统计数据选择的浏览器版本。>=, <和<=也可以运行。
last 2 versions
not ie <= 8
不配置默认为:> 0.5%, last 2 versions, Firefox ESR, not dead
npx browserslist '5%'
npx browserslist '5%' --coverage
> 5%: 基于全球使用率统计而选择的浏览器版本范围。>=,<,<=同样适用。
> 5% in US : 同上,只是使用地区变为美国。支持两个字母的国家码来指定地区。
> 5% in alt-AS : 同上,只是使用地区变为亚洲所有国家。这里列举了所有的地区码。
> 5% in my stats : 使用定制的浏览器统计数据。
cover 99.5% : // 提供覆盖率的大多数流行浏览器。 使用率总和为99.5%的浏览器版本。
cover 99.5% in US : 同上,只是限制了地域,支持两个字母的国家码。
cover 99.5% in my stats :使用定制的浏览器统计数据。
maintained node versions :所有还被 node 基金会维护的 node 版本。
node 10 and node 10.4 : 最新的 node 10.x.x 或者10.4.x 版本。
current node :当前被 browserslist 使用的 node 版本。
extends browserslist-config-mycompany :来自browserslist-config-mycompany包的查询设置
ie 6-8 : 选择一个浏览器的版本范围。
Firefox > 20 : 版本高于20的所有火狐浏览器版本。>=,<,<=同样适用。
ios 7 :ios 7自带的浏览器。
Firefox ESR :最新的火狐 ESR(长期支持版) 版本的浏览器。
unreleased versions or unreleased Chrome versions : alpha 和 beta 版本。
last 2 major versions or last 2 ios major versions :最近的两个发行版,包括所有的次版本号和补丁版本号变更的浏览器版本。
since 2015 or last 2 years :自某个时间以来更新的版本(也可以写的更具体since 2015-03或者since 2015-03-10)
dead :通过last 2 versions筛选的浏览器版本中,全球使用率低于0.5%并且官方声明不在维护或者事实上已经两年没有再更新的版本。目前符合条件的有 IE10,IE_Mob 10,BlackBerry 10,BlackBerry 7,OperaMobile 12.1。
last 2 versions :每个浏览器最近的两个版本。
last 2 Chrome versions :chrome 浏览器最近的两个版本。
defaults :默认配置> 0.5%, last 2 versions, Firefox ESR, not dead。
not ie <= 8 : 浏览器范围的取反。
可以添加not在任和查询条件前面,表示取反
manifest
**webpack.dll.js**
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const webpack = require("webpack")
module.exports = {
mode: 'development',
entry: ['jquery', 'lodash'],
output: {
filename: '[name].dll.js',
path: path.resolve(__dirname, '../dll'),
library: '[name]_[hash]',
},
plugins: [
new CleanWebpackPlugin(),
new webpack.DllPlugin({
context: __dirname,
name: '[name]_[hash]', //映射库的暴露的内容名称
path: path.resolve(__dirname, '../dll/manifest.json')
}),
],
}
**webpack.dev.config.js**
new webpack.DllReferencePlugin({
context: __dirname,
manifest: path.resolve(__dirname, '../dll/manifest.json'),
}),
new AddAssetHtmlWebpackPlugin([{
filepath: path.resolve(__dirname, '../dll/main.dll.js'),
publicPath: "./" // 解决 引入路径 带‘auto’
}])