# webpack5-cli脚手架
# 依赖安装
// 安装webpack相关
// Html-webpack-plugin: 从模板生成一个HTML文件
// webpack-merge:合并配置项
// webpack-dev-server: 开发模式,启动一个本地服务
npm i webpack webpack-cli webpack-dev-server html-webpack-plugin webpack-merge --save-dev
// 清理out目录
npm i clean-webpack-plugin --save-dev
// 样式:css、scss、less
npm i style-loader css-loader sass-loader sass less less-loader --save-dev
// 抽取css
npm i mini-css-extract-plugin --save-dev
// css压缩:webpack4使用'optimize-css-assets-webpack-plugin'
// npm install css-minimizer-webpack-plugin --save-dev
// 处理css样式(背景图url、字体资源url),添加css前缀:autoprefixer用于给css加前缀, cssnano用于压缩优化css
npm i postcss-loader postcss autoprefixer cssnano --save-dev
// 打包进度条
npm i webpackbar --save-dev
// 跨平台,环境变量:process.env
npm i cross-env --save-dev
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// old
"webpack": "^5.48.0",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "^3.11.2",
// new
"webpack": "^5.51.1",
"webpack-cli": "^4.8.0",
"webpack-dev-server": "^4.1.0",
2
3
4
5
6
7
8
9
注意:使用的webpack-dev-server版本是v4,从v3到v4的升级文档,参考这里 (opens new window)。
问题:webpack-dev-server v3版本与webpack5搭配时,overlay选项的message显示不正确。更新到v4后显示正常。
webpack-dev-server v3版本,eslint校验出现error
时,overlay
信息:
升级到v4版本,显示正常:
# 热更新
开发环境热更新,需要设置devServer
的hot
为true,同时配合使用webpack.HotModuleReplacementPlugin (opens new window)才能完全启用HMR。
module.exports = {
devServer: {
hot: true
},
plugins: [
// enable HMR with hot:true
new webpack.HotModuleReplacementPlugin({})
],
}
2
3
4
5
6
7
8
9
注意,如果项目中配置了.browserslistrc
文件,会导致热更新失效。此时需要显示的指定构建目标target
:
module.exports = {
target: "web",// 防止与".browserslistrc" 冲突导致热更新失效
devServer: {
hot: true
},
plugins: [
// enable HMR with hot:true
new webpack.HotModuleReplacementPlugin({})
],
}
2
3
4
5
6
7
8
9
10
# babel配置
babel配置文件可以是.babelrc
文件,或者 babe.config.js
,配置文件名可参考这里Config Files (opens new window)。
npm i @babel/core @babel/cli @babel/preset-env babel-loader --save-dev
.babel.config.js
配置如下
module.exports = {
presets:[
[
"@babel/preset-env", // preset的配置项
]
]
}
2
3
4
5
6
7
# react支持
针对react
,需安装@babel/preset-env
、@babel/preset-react
。
npm i @babel/preset-react --save-dev
npm i react react-dom --save
2
3
同时在.babel.config.js
中添加如下配置:
module.exports = {
presets:[
"@babel/preset-env", // js预设
'@babel/preset-react', // react
]
}
2
3
4
5
6
# vue支持
vue中jsx支持
针对vue
的jsx
,需额外安装插件才支持:
npm i vue --save
npm i vue-loader --save-dev
// vue2
npm i vue-template-compiler --save-dev
// 如果是vue3
// npm i @vue/compiler-sfc --save
// vue中支持jsx
npm i @vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props --save-dev
2
3
4
5
6
7
8
9
10
11
同时在.babel.config.js
配置文件中添加配置以启用vue-jsx
支持:
module.exports = {
presets: [
"@babel/preset-env", // js预设
// '@babel/preset-react', // react
'@vue/babel-preset-jsx' // vue jsx
],
}
2
3
4
5
6
7
.vue
文件解析
为了解析.vue
文件,需要在webpack.dev.config
中配置对应的loader:
let VueLoaderPlugin = require('vue-loader/lib/plugin');
let appSrc = path.resolve(__dirnam, './src');
module.exports = {
resolve: {
modules: [appSrc, 'node_modules'],
// 缺少ts, tsx支持
extensions: ['.js', '.jsx', '.json', '.vue', '.css', '.scss', '.less'],
alias: {
'@': appSrc,
'vue$': 'vue/dist/vue.esm.js'
}
},
module: {
rules: [
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
plugins: [
new VueLoaderPlugin()
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# @babel/preset-env
需要配置@babel/preset-env
插件选项,参考options选项 (opens new window)。
# modules
如果需要启用tree-shaking
,bable.config.js
中需要关闭模块转换 (opens new window)功能。
module.exports = {
presets:[
[
"@babel/preset-env",
{
// "useBuiltIns": "usage",
"loose": false,
"modules": false, // 关闭模块转换,目的是为了启用es6的tree-shaking
}
],
],
// https://babeljs.io/docs/en/assumptions
// "assumptions": {
// "noClassCalls": true
// },
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# loose
宽松模式,默认为false
,主要作用是:将class
类转换为es5代码后,构造函数需要进行this
检查。即只能通过new
的方式使用构造函数。
class Game {
name = 'Violin Charades'
}
const myGame = new Game();
2
3
4
默认情况下(loose为false
),转换后的代码为:
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
// hello.js
var Game = function Game() {
// this检查,Game只能作为构造函数使用(即new操作符)
_classCallCheck(this, Game);
_defineProperty(this, "name", 'Violin Charades');
};
var myGame = new Game();
2
3
4
5
6
7
8
9
10
11
12
13
其他情况下(loose为true
),转换后的代码为:
var Game = function Game() {
// 不做this检查,Game可以作为普通函数调用
this.name = 'Violin Charades';
};
var myGame = new Game();
2
3
4
5
6
需要注意的是:自Babel 7.13,建议使用顶级选项
配置 assumptions
(opens new window), 来配置loose
相关。
module.exports = {
presets:[
[
"@babel/preset-env",
{
"loose": false
}
],
],
// https://babeljs.io/docs/en/assumptions
// "assumptions": {
// "noClassCalls": true
// },
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# useBuiltIns
可参考
babeljs
的try it out (opens new window),在线查看转换结果。
useBuiltIns
: 该选项主要用于配置@babel/preset-env
如何处理polyfills,包括entry
、usage
、false
3个值。
- entry:入口处全部引入
- usage:按需引用
- false:不引入
# entry
业务代码中全量引入:
import 'core-js/stable'
import 'regenerator-runtime/runtime'
2
# usage按需引入
方式1:配合corejs
选项
@babel/polyfill
自7.4.0之后就过时了,建议使用core-js
,并配合corejs
选项来配置
安装core-js
:
npm i core-js@3 --save
# or
// npm i core-js@2 --save
2
3
配置时要注意: 建议指定次要版本,否则 "3" 将被理解为 "3.0"版本,它可能不包括你需要的
feature
。
module.exports = {
presets:[
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"core-js:": { version: "3.16", proposals: true },
}
]
]
}
2
3
4
5
6
7
8
9
10
11
方式2:@babel/plugin-transform-runtime插件,配合@babel/runtime
@babel/plugin-transform-runtime (opens new window)配合@babel/runtime (opens new window),在编写library
库的时候,推荐使用。可参考官方文档 (opens new window)。
关于@babel/runtime
的介绍,也可以参考这篇文章 (opens new window)。
@babel/plugin-transform-runtime: 其主要作用就是,复用babel inject出来的公共函数。默认情况下,是在使用的地方inject出来代码。配置该插件后,则换成从统一的入口引入。
npm i @babel/runtime @babel/runtime-corejs3 --save
// @babel/plugin-transform-runtime配置corejs时,需要安装@babel/runtime-corejs3
npm i @babel/plugin-transform-runtime --save-dev
2
3
4
配置如下:
module.exports = {
presets:[
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"core-js:": { version: "3.16", proposals: true },
}
]
],
plugins: [
[ // polyfill方案1升级,目的是复用babel的helper函数
"@babel/plugin-transform-runtime",
{
"corejs": 3
}
]
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
举例说明:
可使用babeljs的在线编译 (opens new window),查看结果
// 1.js
class Person{}
2
当我们采用方式1时,babel
编译结果如下:
"use strict";
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var Person = function Person() {
_classCallCheck(this, Person);
};
2
3
4
5
6
7
8
9
10
11
12
当我们采用方式2时,babel编译结果为:
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var Person = function Person() {
(0, _classCallCheck2["default"])(this, Person);
};
2
3
4
5
6
7
我们会发现:
1、方式2复用了_classCallCheck
这个方法,换成了从@babel/runtime
中引入。这样,即使有100个js文件,_classCallCheck
也只会有一份。
2、方式1则是直接将代码拷贝到了页面中。如果有100个js文件,则会产生100个_classCallCheck
函数。
# browserslist
Browsersllist (opens new window): 作用是在
babel
转义时,根据配置判断需要引入哪些polyfill。可以配置
.browserslist
文件或者babe.config.js
中配置targets
属性。优点:高版本浏览器(或者非IE环境下),很多代码不需要进行
polyfill
,可以大幅度减小代码输出体积。
安装:
npm i browserslist --save
配置.browserslist
文件
> 0.2%
Firefox ESR
not IE 11
2
3
或者在babel.config.js
中配置targets
属性
module.exports = {
// 对象方式
// targets: {
// "chrome": "65",
// "firefox": "",
// // "ie": 11,
// },
// 字符串格式
// targets: '> 0.5%, last 2 versions, Firefox ESR, not dead, not IE 11',
}
2
3
4
5
6
7
8
9
10
配置完成后,即可在命令行中执行npx browserslist
查看支持的浏览器结果:
# 参考
# plugins
# CopyWebpackPlugin
用于文件拷贝,安装:
npm install copy-webpack-plugin --save-dev
使用:
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{ from: "source", to: "dest" },
{ from: "other", to: "public" },
],
}),
],
};
2
3
4
5
6
7
8
9
10
11
12
# ESLintWebpackPlugin
主要用于开发环境/生成环境
检查代码规范。
webpack5之后,eslint-loader
已经被弃用,推荐使用eslint-webpack-plugin. (opens new window),中文文档在这里 (opens new window)。
安装插件:
npm install eslint-webpack-plugin --save-dev
配置插件:
const ESLintWebpackPlugin = require('eslint-webpack-plugin');
module.exports = {
// elinst校验,替代旧的eslint-loader
new ESLintPlugin({
exclude: ['node_modules'],
files: ['.', 'src', 'config'],
formatter: 'table',
// extensions: ['js', 'jsx'],
extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue'], // 添加对.vue的校验,默认只支持js后缀
emitError: true, // 发射错误信息
emitWarning: true, // 发射告警信息
// 只有在mode为'production'时,当出现eslint错误时,构建才会fail。
// https://github.com/webpack-contrib/eslint-webpack-plugin/issues/51#issuecomment-768213066
failOnError: true, // 默认true,出现eslint error的时候,构建fail。
// failOnWarning: true, // 默认false,出现eslint warning的时候,构建fail。
}),
// ...
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
注意:
只有当webpack的
mode
为production
时,同时配置failOnError
为true
时,如果出现eslint error
,webpack才能阻止构建。否则,eslint虽然会校验错误,但是不影响正常的构建打包过程。
eslint校验失败后,message中文乱码问题
升级webpack-dev-server到v4版本即可
# terser-webpack-plugin
用于覆盖webpack中关于terser-webpack-plugin
的默认配置。
安装:
// 注意:webpack5及以上,内部自带该插件,不需要再安装
npm install terser-webpack-plugin --save-dev
2
配置:
module.exports = {
optimization: {
concatenateModules: true,//开启scope-hoisting
minimize: true, // 开启webpack压缩
minimizer: [ // 自定义TerserWebpackPlugin实例配置
new TerserWebpackPlugin({
parallel: true,/** 开启多进程并行压缩 */
// test: /\.js(\?.*)?$/i, // 压缩js文件
extractComments: false, // 不抽取注释
})
],
},
};
2
3
4
5
6
7
8
9
10
11
12
13
# DefinePlugin (opens new window) vs EnvironmentPlugin (opens new window)
DefinePlugin
module.exports = {
plugins: [
// 环境变量:DefinePlugin vs EnvironmentPlugin
new webpack.DefinePlugin({
"process.env.debug": true,
"process.env.test": JSON.stringify("test"),
"PRODUCTION": JSON.stringify(true), // bool值
"VERSION": JSON.stringify('v1'), // 字符串
})
],
}
2
3
4
5
6
7
8
9
10
11
index.js
输出:
console.log("process.env.debug", process.env.debug); // true, 布尔值
console.log("process.env.test", process.env.test); // "test",字符串
console.log("PRODUCTION", PRODUCTION); // true,布尔值
console.log("VERSION", VERSION); // 'v1',字符串
2
3
4
我们也可以通过@vue/cli
提供的inspect (opens new window)命令,查看默认的webpack的配置:
通过@vue/cli创建的项目,内置vue-cli-service并提供了inspect命令
{
"scripts": {
"inspect:prod": "vue-cli-service inspect --mode='production'> config.prod.js",
"inspect:dev": "vue-cli-service inspect --mode='development'> config.dev.js",
}
}
2
3
4
5
6
7
我们可以看到其中DefinePlugin
的用法:
/* config.plugin('define') */
new DefinePlugin(
{
'process.env': {
NODE_ENV: '"development"',
BASE_URL: '"/"'
}
}
),
2
3
4
5
6
7
8
9
EnvironmentPlugin
The
EnvironmentPlugin
is shorthand for using theDefinePlugin
(opens new window) onprocess.env
(opens new window) keys.即:
EnvironmentPlugin
等效于:DefinePlugin
在使用时,key为process.env
上的简写
module.exports = {
plugins: [
new webpack.EnvironmentPlugin({
test: 'test',
debug: true,
})
]
}
// 等效于:
// process.env.test设置为字符串'test'
// process.env.debug设置为布尔值true
2
3
4
5
6
7
8
9
10
11
index.js输出:
console.log("process.env.debug", process.env.debug); // true, 布尔值
console.log("process.env.test", process.env.test); // "test",字符串
2
参考:
# eslint
代码格式校验
eslint-webpack-plugin
可用于开发阶段的代码校验
该插件诞生的目的是解决eslint-loader (opens new window)存在的问题,可参考文档 (opens new window)。
选项 | eslint-webpack-plugin | eslint-loader |
---|---|---|
配置简单 | YES | NO |
生成唯一的输出报告 | YES | NO |
直接使用 eslint 的缓存 | YES | NO |
仅改变文件 | YES | NO |
# webpack中校验
npm install eslint-webpack-plugin eslint --save-dev
# 命令行校验
npm install eslint @babel/core @babel/eslint-parser -D
// for vue
// npm i eslint-plugin-vue --save-dev
// for react
// npm i eslint-plugin-react --save-dev
2
3
4
5
6
7
8
9
初始化eslint配置,可通过eslint --init
命令:
1、如何使用eslint
// ? How would you like to use ESLint?
To check syntax only
❯ To check syntax and find problems
To check syntax, find problems, and enforce code style
2
3
4
2、使用的js模块类型
// ? What type of modules does your project use? …
❯ JavaScript modules (import/export)
CommonJS (require/exports)
None of these
2
3
4
3、使用哪个框架
当选用了
Vue
时,需要安装eslint-plugin-vue (opens new window)插件当选用了
React
时,需要安装eslint-plugin-react (opens new window)插件
? Which framework does your project use? …
❯ React
Vue.js
None of these
2
3
4
4、是否使用ts
? Does your project use TypeScript? › No / Yes
5、代码运行环境
? Where does your code run? … (Press <space> to select, <a> to toggle all, <i> to invert selection)
✔ Browser
✔ Node
2
3
6、生成配置文件格式
? What format do you want your config file to be in? …
❯ JavaScript
YAML
JSON
2
3
4
注意:
需要指定
parser
为@babel/eslint-parser
'parser': '@babel/eslint-parser'
1React17
及以上(如果需要启用jsx检查),需要配置react
的版本信息"settings": { "react": { "version": "detect" } }
1
2
3
4
5
最终根据生成的.eslintrc.js
修改后的配置文件,支持vue、react。
module.exports = {
'root': true,
'env': {
'browser': true,
'es2021': true,
'node': true
},
'extends': [
'eslint:recommended',
// react
'plugin:react/recommended',
// vue
// 'plugin:vue/recommended' // Use this if you are using Vue.js 2.x.
// "plugin:vue/essential",
// 'plugin:vue/vue3-recommended', // for Vue.js 3
],
'parser': 'vue-eslint-parser', // vue需要配置自己的parser
// 'parser': '@babel/eslint-parser', //
'parserOptions': {
'parser': '@babel/eslint-parser',
'ecmaVersion': 10,
// https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser
// 'ecmaVersion': 12, // Parsing error: Unexpected token import (eslint)
'sourceType': 'module',
'ecmaFeatures': {
'jsx': true
},
},
'plugins': [
'react',
'vue'
],
// react17之后,需要指定version版本
// https://github.com/yannickcr/eslint-plugin-react/issues/2157
"settings": {
"react": {
"version": "detect"
}
},
'rules': {
// .vue rule
'vue/singleline-html-element-content-newline': ['off'],
'vue/max-attributes-per-line': ['error', {
'singleline': {
'max': 8,
'allowFirstLine': true
},
'multiline': {
'max': 1,
'allowFirstLine': false
}
}],
'vue/html-indent': ['error', 4],
'quotes': ['error', 'single'],
'indent': ['error', 4],
'no-unused-vars': ['error'],
'no-irregular-whitespace': ['error', {skipComments: true}], // 禁止不规则的空白
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
注意:
1、"eslint:recommended"
启用的是在 规则页面 (opens new window) 中被标记为✅ 的规则,"eslint:all"
指的是所有的eslint规则。
2、我们可以根据自己项目需求,扩展自己的eslint
规则,参考使用可共享的npm包 (opens new window)、可共享配置 (opens new window)。也可以使用其他的扩展(以eslint-config-
开头的npm包)。可参考eslint-config-ivweb (opens new window)、eslint-config-alloy (opens new window)。
# 参考
- js代码规范之---Eslint安装与配置 (opens new window)
- 制定自己团队的前端开发规范 (opens new window)
- React项目配置ESlint总结 (opens new window)
- 细嚼慢咽 Typescript + React17 +Eslint + Git hook 工作流 (opens new window)
- React version not specified in eslint-plugin-react settings #2157 (opens new window)
- eslint规范:https://github.com/ecomfe/eslint-config
- eslint-webpack-plugin failing the build despite having failOnError set to false (opens new window)#51
vscode中配置eslint
自动修复:
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true, // 保存时自动修复
},
2
3
# husky + lint-staged
# lint-staged
lint-staged,一个仅仅过滤出 Git 代码暂存区文件(被 git add 的文件)的工具。即:只检测暂存区的代码是否符合规范。
安装:
npm i lint-staged --save-dev
lint-staged配置:
创建.lintstagedrc.js
文件,并写入如下内容:
module.exports = {
// 执行'lint-staged'时的指令集合
"*.{js,jsx,vue}": [
"eslint src",
"git add"
]
};
2
3
4
5
6
7
8
或者在package.json
中配置lint-staged
选项,配置的优先级参考这里 (opens new window)。
{
"lint-staged": {
"*.{js,jsx,vue}": [
"eslint --fix src",
"git add"
]
},
// 执行'npm run preCommit'命令,就会执行'lint-staged'
"scripts": {
"preCommit": "lint-staged"
}
}
2
3
4
5
6
7
8
9
10
11
12
# husky
作用:方便处理Git的各种钩子
# Git Hooks钩子
常用的git钩子,参考Git Hooks钩子 (opens new window)
名称 | 说明 | 绕过方法 |
---|---|---|
pre-commit | 由 git commit 调用,在 commit 之前执行。检查即将提交的快照,以非 0 退出时 ,中断此次提交。可以用于代码的格式检查、运行测试用例等 | --no-verify参数 |
commit-msg | 由 git commit 或 git merge 调用,以非 0 状态码退出时,会中断此次操作。可以用于对提交信息的校验。可参考这片文章 (opens new window)中关于commitlint 的使用 | --no-verify参数 |
pre-merge-commit | 由 git merge 调用,在 merge 之前执行,以非 0 状态退出时,会中断此次合并 | --no-verify参数 |
pre-push | 被 git push 调用,在 git push 前执行,防止进行推送,以非 0 状态码退出时,会中断此次推送 |
# husky安装
安装husky:
npm i husky --save-dev
启用hooks钩子:
npx husky install // Enable Git hooks
// npm uninstall husky
2
如果没有安装npx
,则全局安装npx
npm install -g npx
添加一条script
脚本命令:
// npm v7版本才支持'set-script'命令
// npm v6版本可以直接编辑package.json,直接添加一条'prepare'指令
npm set-script prepare "husky install"
2
3
其作用就是在package.json
中添加了一条prepare
指令,如下所示:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1", // 测试用:返回1,提交失败
"test": "echo \"Success\" && exit 0", // 测试用:返回0,正常提交
"prepare": "husky install"
}
2
3
4
5
添加一个husky
钩子:
npx husky add .husky/pre-commit "npm test"
执行完 该命令后,会在.husky
目录下生成一个名为pre-commit
的shell脚本文件,如下图所示:
钩子作用:在
commit
之前,调用pre-commit
钩子。而在该钩子内部,会执行npm test
命令,如果执行失败,则自动中断commit
指令。
添加一条commit
信息,用于测试钩子是否生效:
git add .husky/pre-commit
git commit -m "Keep calm and commit" // npm test返回非0,执行失败 --> commit失败
2
由于
npm test
命令返回了1
,因此,commit会失败。
# @vue/cli中的配置
如下为@Vue/cli
中lint and fix on commit
的配置:
@vue/cli中package.json中的的
gitHooks
配置,需要安装yorkie (opens new window)包
// 1 用于commit,触发pre-commit钩子
// 2 该钩子调用lint-staged
// 3 如果校验通过,则执行`lint-staged`选项中配置的命令
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,vue}": [
"vue-cli-service lint",
"git add"
]
}
2
3
4
5
6
7
8
9
10
11
12
整个流程为:
- commit触发hooks的
pre-commit
钩子。 - pre-commit执行
lint-staged
进行校验。
# 参考文章
- 掘金
- segmentfault
- 简书
# commitizen
git commit
msg提交规范
✨ feat:新功能
🐞 fix:修补bug
📃 docs:修改文档
🌈 style: 格式化代码结构,没有逻辑上的代码修改
🦄 refactor:重构,即不是新增功能,也不是修改bug的代码变动,比如重命名变量
🎈 perf: 性能优化
🧪 test:增加测试代码,单元测试用例
🔧 build:依赖相关内容
🐎 ci:ci配置相关,例如k8s,docker配置的修改
🐳 chore:改变构建流程
↩ revert: 版本回滚
2
3
4
5
6
7
8
9
10
11
# 发布lib
# verdaccio
使用verdaccio作为自由的npm仓库,使用方式可参考官网。使用pm2
管理服务。
# 添加用户
npm adduser --registry http://121.199.54.25:32000
# 发布
npm publish --registry http://121.199.54.25:32000
# 卸载
npm unpublish --force
2
3
4
5
6
7
通过verdaccio
命令,可查看配置文件
、服务地址
等
配置文件路径:/root/.config/verdaccio/config.yaml
# 参考
- verdaccio介绍 (opens new window)
- NPM私库搭建-verdaccio (opens new window)
- verdaccio - 快速搭建私有npm registry的利器 (opens new window)
# sourcemap
方案1、默认生成sourcemap
webpack配置如下:
module.exports = {
devtool: 'sourcemap'
}
2
3
该方式会产生一个对应的sourcemap
文件,同时在js
源文件末尾会追加对应的map源文件
的映射地址。
//# sourceMappingURL=index.3fe79d61.bundle.js.map
方案2、通过SourceMapDevToolPlugin
来产生sourcemap
webpack配置如下:
module.exports = {
// 注意SourceMapDevToolPlugin和devtool不可共存
devtool: false, // false, source-map
plugins: [
new webpack.SourceMapDevToolPlugin({
filename: '[file].map',
append: '\n//# sourceMappingURL=https://example.com/sourceMap/[url]'
]
};
2
3
4
5
6
7
8
9
该方式类似方案1,会产生一个对应的sourcemap
文件,同时在js
源文件末尾会追加对应的map源文件
的映射地址。
注意:此方式会修改追加的映射地址
//# sourceMappingURL=https://example.com/sourceMap/index.3fe79d61.bundle.js.map
主要目的:
1、线上代码不放sourcemap
,防止代码泄漏。
2、线上代码 出现问题,可方便本地调试。具体方式为:我们可以在本地host中添加一个域名https://example.com/sourceMap,并将它指向我们本地sourcemap服务器。
// host
https://example.com 192.168.4.200
2
# 参考
# FAQ
如何在
html
文件中读取htmlWebpackPlugin
配置项的值?可参考vue-cli
的BASE_URL
取值?1、
BASE_URL
是通过DefinePlugin全局注入的变量;2、环境变量,是通过npm包
dotenv
来读取本地的.env
文件。VUE CLI3的环境变量 (opens new window)也是使用的这个插件。3、在html中添加如下代码
<div><%= JSON.stringify(htmlWebpackPlugin) %></div>
,即可输出htmlWebpackPlugin
的所有配置项。或者查看html-webpack-plugin (opens new window)文档。new webpack.DefinePlugin({ "BASE_URL": JSON.stringify('https://api.example.com'), // 'process.env': { // NODE_ENV: JSON.stringify(process.env.NODE_ENV) // } }),
1
2
3
4
5
6htmlWebpackPlugin
配置项的值如下图所示:如何协调本地开发与线上调试中关于
sourcemap
的问题?配合SourceMapDevToolPlugin,或者本地代理.
map
文件的访问。external (opens new window)引入问题
key为对应的模块名,value可以是字符串,或者对象:
- value为字符串:其值为对应的库,挂载到"window"上的属性值
- value为对象:参考external value is an object (opens new window)。需要注意的是,如果value为
object
时,则打包的lib库的libraryTarget
必须为umd
,其他情况下不支持。
const externalCfg= { // 当value为对象的方式有问题,对于react、react-dom的module.exports都是undefined, // 参考:https://webpack.js.org/configuration/externals/#object // 原因:当value为对象时,只支持libraryTarget为'umd'. 当libraryTarget为其他值时不生效。 // 'react': { // root: 'React', commonjs2: 'react', commonjs: 'react', amd: 'react', // }, // 'react-dom': { // root: 'ReactDOM', commonjs2: 'react-dom', commonjs: 'react-dom', amd: 'react-dom', // }, // 字符串方式:cdn外链引入正常, 'react': 'React', // module.exports = React 'react-dom': 'ReactDOM', // module.exports = ReactDOM // 字符串方式:cdn外链引入正常 // 注:值:"React"、"ReactDOM"指的是对应的库,挂载到"window"上的属性值。 "react": "React", // module.exports = React "react-dom": "ReactDOM", // module.exports = ReactDOM };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18当项目中通过
vue-eslint-parser
对.vue
进行eslint
校验时,如下2种情况,对于() *=>* import('../xx.vue')
语法会报错。1、
parserOptions
选项中没有配置'parser': '@babel/eslint-parser'
,参考eslint-plugin-vue
中的how-to-use-a-custom-parser (opens new window)。2、或者
ecmaVersion
版本较低时(小于等于10);解决办法:
parserOptions
选项中配置添加'parser': '@babel/eslint-parser'
,参考specifying-parser (opens new window);ecmaVersion
版本改为>=11
(即2020后的语法提案),参考specifying-parser-options (opens new window)中的ecmaVersion
配置;// @babel/plugin-syntax-dynamic-import // NOTE: This plugin is included in @babel/preset-env, in ES2020(ecma11版本)
1
2
module.exports = { 'parser': 'vue-eslint-parser', // vue eslint parser(vue配置) 'parserOptions': { 'parser': '@babel/eslint-parser', // 自定义parser // "ecmaVersion": 6, // For ES6 syntax 'ecmaVersion': 10, 'sourceType': 'module', 'ecmaFeatures': { 'jsx': true }, }, }
1
2
3
4
5
6
7
8
9
10
11
12