1 為什么需要babel种樱?
事實(shí)上,在開發(fā)中我們很少直接去接觸babel俊卤,但是babel對(duì)于前端開發(fā)來說嫩挤,目前是不可缺少的一部分。原因如下:
- 開發(fā)中消恍,我們想要使用ES6+的語法岂昭,想要使用TypeScript,開發(fā)React項(xiàng)目狠怨,它們都是離不開Babel的
- 學(xué)習(xí)Babel對(duì)于我們理解代碼從編寫到線上的轉(zhuǎn)變過程直觀重要
- 了解真相惧磺,你才能獲得真知的自由
那么反璃,Babel到底是什么呢么夫?
Babel
是一個(gè)工具鏈沸枯,主要用于舊瀏覽器或者緩解中將ECMAScript 2015+代碼轉(zhuǎn)換為向后兼容版本的JavaScript无宿。包括:語法轉(zhuǎn)換茵汰、源代碼轉(zhuǎn)換、Polyfill實(shí)現(xiàn)目標(biāo)緩解缺少的功能等孽鸡。
2 Babel命令行使用
babel本身可以作為一個(gè)獨(dú)立的工具(和postcss一樣)蹂午,不和webpack等構(gòu)建工具配置來單獨(dú)使用栏豺。如果我們希望在命令行嘗試使用babel,需要安裝如下庫:
yarn add @babel/cli @babel/core -D
- @babel/core:babel的核心代碼豆胸,必須安裝
- @babel/cli:可以讓我們?cè)诿钚惺褂胋abe
使用babel來處理我們的源代碼:
npx babel src --out-dir dist
src:源文件的目錄奥洼。
--out-dir:指定要輸出的文件夾dist。
2.1 插件的使用
比如我們需要轉(zhuǎn)換箭頭函數(shù)晚胡,那么我們就可以使用箭頭函數(shù)轉(zhuǎn)換相關(guān)的插件
yarn add @babel/plugin-transform-arrow-functions -D
npx babel src --out-dir dist --plugins=@babel/plugin-transform-arrow-functions
const轉(zhuǎn)成 var:
yarn add @babel/plugin-transform-block-scoping -D
npx babel src --out-dir dist --plugins=@babel/plugin-transform-block-scoping
,@babel/plugin-transform-arrow-functions
2.3 Babel的預(yù)設(shè)preset
但是如果要轉(zhuǎn)換的內(nèi)容過多灵奖,一個(gè)個(gè)設(shè)置是比較麻煩的,我們可以使用預(yù)設(shè)(preset)估盘,后面我們?cè)倬唧w來講預(yù)設(shè)代表的含義瓷患。
yarn add @babel/preset-env -D
npx babel src --out-dir dist --presets=@babel/preset-env
3 Babel的底層原理
babel是如何做到將我們的一段代碼(ES6、TypeScript遣妥、React)轉(zhuǎn)成另外一段代碼(ES5)的呢擅编?
從一種源代碼(原生語言)轉(zhuǎn)換成另一種源代碼(目標(biāo)語言),這是什么的工作呢箫踩?
就是編譯器爱态,事實(shí)上我們可以將babel看成就是一個(gè)編譯器。Babel編譯器的作用就是將我們的源代碼境钟,轉(zhuǎn)換成瀏覽器可以直接識(shí)別的另外一段源代碼锦担。
3.1 babel編譯器執(zhí)行原理
Babel的執(zhí)行階段:
當(dāng)然,這只是一個(gè)簡化版的編譯器工具流程吱韭,在每個(gè)階段又會(huì)有自己具體的工作:
以下面代碼為例:
const name = "coderwhy";
const foo = (name) => console.log(name);
foo(name);
首先吆豹,babel通過此法分析生成tokens數(shù)組
,生成結(jié)構(gòu)如下:
[
{
"type": "Keyword",
"value": "const"
},
{
"type": "Identifier",
"value": "foo"
},
{
"type": "Punctuator",
"value": "="
},
{
"type": "Punctuator",
"value": "("
},
{
"type": "Identifier",
"value": "name"
},
{
"type": "Punctuator",
"value": ")"
},
{
"type": "Punctuator",
"value": "=>"
},
{
"type": "Identifier",
"value": "console"
},
{
"type": "Punctuator",
"value": "."
},
{
"type": "Identifier",
"value": "log"
},
{
"type": "Punctuator",
"value": "("
},
{
"type": "Identifier",
"value": "name"
},
{
"type": "Punctuator",
"value": ")"
},
{
"type": "Punctuator",
"value": ";"
},
{
"type": "Identifier",
"value": "foo"
},
{
"type": "Punctuator",
"value": "("
},
{
"type": "String",
"value": "\"coderwhy\""
},
{
"type": "Punctuator",
"value": ")"
},
{
"type": "Punctuator",
"value": ";"
}
]
其次理盆,babel通過語法分析(parsing)生成AST(抽象語法樹):
{
"type": "Program",
"body": [
{
"type": "VariableDeclaration",
"declarations": [
{
"type": "VariableDeclarator",
"id": {
"type": "Identifier",
"name": "foo"
},
"init": {
"type": "ArrowFunctionExpression",
"id": null,
"params": [
{
"type": "Identifier",
"name": "name"
}
],
"body": {
"type": "CallExpression",
"callee": {
"type": "MemberExpression",
"computed": false,
"object": {
"type": "Identifier",
"name": "console"
},
"property": {
"type": "Identifier",
"name": "log"
}
},
"arguments": [
{
"type": "Identifier",
"name": "name"
}
]
},
"generator": false,
"expression": true,
"async": false
}
}
],
"kind": "const"
},
{
"type": "ExpressionStatement",
"expression": {
"type": "CallExpression",
"callee": {
"type": "Identifier",
"name": "foo"
},
"arguments": [
{
"type": "Literal",
"value": "coderwhy",
"raw": "\"coderwhy\""
}
]
}
}
],
"sourceType": "script"
}
接著痘煤,babel遍歷AST后進(jìn)行訪問操作,并通過相應(yīng)的插件轉(zhuǎn)成新的AST:
{
"type": "Program",
"body": [
{
"type": "VariableDeclaration",
"declarations": [
{
"type": "VariableDeclarator",
"id": {
"type": "Identifier",
"name": "foo"
},
"init": {
"type": "FunctionExpression",
"id": {
"type": "Identifier",
"name": "foo"
},
"params": [
{
"type": "Identifier",
"name": "name"
}
],
"body": {
"type": "BlockStatement",
"body": [
{
"type": "ReturnStatement",
"argument": {
"type": "CallExpression",
"callee": {
"type": "MemberExpression",
"computed": false,
"object": {
"type": "Identifier",
"name": "console"
},
"property": {
"type": "Identifier",
"name": "log"
}
},
"arguments": [
{
"type": "Identifier",
"name": "name"
}
]
}
}
]
},
"generator": false,
"expression": false,
"async": false
}
}
],
"kind": "var"
},
{
"type": "ExpressionStatement",
"expression": {
"type": "CallExpression",
"callee": {
"type": "Identifier",
"name": "foo"
},
"arguments": [
{
"type": "Literal",
"value": "coderwhy",
"raw": "\"coderwhy\""
}
]
}
}
],
"sourceType": "script"
}
最后生成目標(biāo)代碼啦:
var name = "coderwhy";
var foo = function foo(name) {
return console.log(name);
};
foo(name);
4. webpack使用babel
4.1 babel-loader
在實(shí)際開發(fā)中猿规,我們通常會(huì)在構(gòu)建工具中通過配置babel來對(duì)其進(jìn)行使用的衷快,比如在webpack中。
那么我們就需要去安裝相關(guān)的依賴:
- 如果之前已經(jīng)安裝了@babel/core姨俩,那么這里不需要再次安裝蘸拔;
yarn add babel-loader @babel/core -D
我們可以設(shè)置一個(gè)規(guī)則,在加載js文件時(shí)环葵,使用我們的babel:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.m?js$/,
use: {
loader: 'babel-loader'
}
}
]
}
}
4.2 指定使用的插件
我們必須指定使用的插件才會(huì)生效:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.m?js$/,
use: {
loader: 'babel-loader',
options: {
plugins: [
'@babel/plugin-transform-arrow-functions',
'@babel/plugin-transform-block-scoping'
]
}
}
}
]
}
}
4.3 babel-preset
如果我們一個(gè)個(gè)去安裝使用插件调窍,那么需要手動(dòng)來管理大量的babel插件,我們可以直接給webpack提供一個(gè)preset张遭,webpack會(huì)根據(jù)我們的預(yù)設(shè)來加載對(duì)應(yīng)的插件列表邓萨,并且將其傳遞給babel。
安裝preset-env:
yarn add @babel/preset-env -D
配置:
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.m?js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env'
]
}
}
}
]
}
}
4.4 設(shè)置目標(biāo)瀏覽器 browserslist
我們最終打包的JavaScript代碼,是需要跑在目標(biāo)瀏覽器上的缔恳,那么如何告知babel我們的目標(biāo)瀏覽器呢宝剖?
- browserslist工具,之前在
postcss
已經(jīng)配置過了歉甚。 - target屬性
module.exports = {
module: {
rules: [
{
test: /\.m?js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
targets: 'chrome 87'
}]
]
}
}
}
]
}
}
target的優(yōu)先級(jí)高于browserslist万细,也就是說,當(dāng)設(shè)置target后纸泄,browserlist的配置會(huì)失效赖钞。但我們開發(fā)中推薦在browserlist里配置,這樣能和postcss同步刃滓。
4.5 Stage-X的preset
要了解Stage-X仁烹,我們需要先了解一下TC39的組織:
- TC39是指技術(shù)委員會(huì)(Technical Committee)第 39 號(hào);
- 它是 ECMA 的一部分咧虎,ECMA 是 “ECMAScript” 規(guī)范下的 JavaScript 語言標(biāo)準(zhǔn)化的機(jī)構(gòu)卓缰;
- ECMAScript 規(guī)范定義了 JavaScript 如何一步一步的進(jìn)化、發(fā)展砰诵;
TC39 遵循的原則是:分階段加入不同的語言特性征唬,新流程涉及四個(gè)不同的 Stage:
- Stage 0:strawman(稻草人),任何尚未提交作為正式提案的討論茁彭、想法變更或者補(bǔ)充都被認(rèn)為是第 0 階段的"稻草人"总寒;
- Stage 1:proposal(提議),提案已經(jīng)被正式化理肺,并期望解決此問題摄闸,還需要觀察與其他提案的相互影響;
- Stage 2:draft(草稿)妹萨,Stage 2 的提案應(yīng)提供規(guī)范初稿年枕、草稿。此時(shí)乎完,語言的實(shí)現(xiàn)者開始觀察 runtime 的具體實(shí)現(xiàn)是否合理熏兄;
- Stage 3:candidate(候補(bǔ)),Stage 3 提案是建議的候選提案树姨。在這個(gè)高級(jí)階段摩桶,規(guī)范的編輯人員和評(píng)審人員必須在最終規(guī)范上簽字。Stage 3 的提案不會(huì)有太大的改變帽揪,在對(duì)外發(fā)布之前只是修正一些問題硝清;
- Stage 4:finished(完成),進(jìn)入 Stage 4 的提案將包含在 ECMAScript 的下一個(gè)修訂版中转晰;
4.1.1 Babel的Stage-X設(shè)置
在babel7之前(比如babel6中)芦拿,我們會(huì)經(jīng)忱危看到這種設(shè)置方式:
- 它表達(dá)的含義是使用對(duì)應(yīng)的 babel-preset-stage-x 預(yù)設(shè)
- 但是從babel7開始,已經(jīng)不建議使用了防嗡,建議使用preset-env來設(shè)置;
5 Babel的配置文件
像之前一樣侠坎,我們可以將babel的配置信息放到一個(gè)獨(dú)立的文件中蚁趁,babel給我們提供了兩種配置文件的編寫:
- babel.config.json(或者.js,.cjs实胸,.mjs)文件他嫡;
- .babelrc.json(或者.babelrc,.js庐完,.cjs钢属,.mjs)文件;
它們兩個(gè)有什么區(qū)別呢门躯?目前很多的項(xiàng)目都采用了多包管理的方式(babel本身淆党、element-plus、umi等)讶凉;
- .babelrc.json:早期使用較多的配置方式染乌,但是對(duì)于配置Monorepos項(xiàng)目是比較麻煩的;
- babel.config.json(babel7):可以直接作用于Monorepos項(xiàng)目的子包懂讯,更加推薦荷憋;
在項(xiàng)目根目錄新建babel.config.js文件
:
module.exports = {
presets: [
['@babel/preset-env']
]
}
然后移除webpack.config.js
的babel配置:
module.exports = {
module: {
rules: [
{
test: /\.m?js$/,
use: {
loader: 'babel-loader',
}
}
]
}
}
6 認(rèn)識(shí)polyfill
Polyfill是什么呢?
- 翻譯:一種用于衣物褐望、床具等的聚酯填充材料, 使這些物品更加溫暖舒適勒庄;
- 理解:更像是應(yīng)該填充物(墊片),一個(gè)補(bǔ)丁瘫里,可以幫助我們更好的使用JavaScript实蔽;
為什么時(shí)候會(huì)用到polyfill呢?
- 比如我們使用了一些語法特性(例如:Promise, Generator, Symbol等以及實(shí)例方法例如
Array.prototype.includes等) - 但是某些瀏覽器壓根不認(rèn)識(shí)這些特性减宣,必然會(huì)報(bào)錯(cuò)盐须;
- 我們可以使用polyfill來填充或者說打一個(gè)補(bǔ)丁,那么就會(huì)包含該特性了漆腌;
6.1 如何使用polyfill贼邓?
babel7.4.0之前,可以使用 @babel/polyfill的包闷尿,但是該包現(xiàn)在已經(jīng)不推薦使用了塑径。
babel7.4.0之后,可以通過單獨(dú)引入core-js和regenerator-runtime來完成polyfill的使用:
yarn add core-js regenerator-runtime --save
在webpack.configf.js
中排除node_modules的文件填具。因?yàn)楹芏嗟谌桨鼉?nèi)部已經(jīng)實(shí)現(xiàn)了polyfill了统舀,會(huì)引起沖突匆骗。
module.exports = {
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
}
}
]
}
}
配置babel.config.js
我們需要在babel.config.js文件中進(jìn)行配置,給preset-env配置一些屬性:
- useBuiltIns:設(shè)置以什么樣的方式來使用polyfill誉简;
- corejs:設(shè)置corejs的版本碉就,目前使用較多的是3.x的版本,比如我使用的是3.8.x的版本闷串;
- 另外corejs可以設(shè)置是否對(duì)提議階段的特性進(jìn)行支持瓮钥;設(shè)置 proposals屬性為true即可;
useBuiltIns屬性設(shè)置
useBuiltIns屬性有三個(gè)常見的值
- 第一個(gè)值:false
- 打包后的文件不使用polyfill來進(jìn)行適配烹吵;
- 并且這個(gè)時(shí)候是不需要設(shè)置corejs屬性的碉熄;
- 第二個(gè)值:usage
- 會(huì)根據(jù)源代碼中出現(xiàn)的語言特性,自動(dòng)檢測(cè)所需要的polyfill肋拔;
- 這樣可以確保最終包里的polyfill數(shù)量的最小化锈津,打包的包相對(duì)會(huì)小一些;
- 可以設(shè)置corejs屬性來確定使用的corejs的版本;
module.exports = {
presets: [
['@babel/preset-env', {
useBuiltIns: 'usage',
corejs: 3 // 默認(rèn)值2版本凉蜂,我們安裝的是3
}]
]
}
- 第三個(gè)值:entry
- 如果我們依賴的某一個(gè)庫本身使用了某些polyfill的特性琼梆,但是因?yàn)槲覀兪褂玫氖莡sage,所以之后用戶瀏覽器可能會(huì)報(bào)錯(cuò)跃惫;
- 所以叮叹,如果你擔(dān)心出現(xiàn)這種情況,可以使用 entry爆存;
- 并且需要在入口文件中添加 `import 'core-js/stable'; import 'regenerator-runtime/runtime';
- 這樣做會(huì)根據(jù) browserslist 目標(biāo)導(dǎo)入所有的polyfill蛉顽,但是對(duì)應(yīng)的包也會(huì)變大;
useBuiltIns值解讀:
babel.config.js
module.exports = {
presets: [
['@babel/preset-env', {
useBuiltIns: 'entry',
corejs: 3
}]
]
}
main.js
import 'core-js/stable';
import 'regenerator-runtime/runtime'
new Promise (resolve => {
resolve(2)
})
6.2 認(rèn)識(shí)Plugin-transform-runtime(了解)
在前面我們使用的polyfill先较,默認(rèn)情況是添加的所有特性都是全局的
- 如果我們正在編寫一個(gè)工具庫携冤,這個(gè)工具庫需要使用polyfill;
- 別人在使用我們工具時(shí)闲勺,工具庫通過polyfill添加的特性曾棕,可能會(huì)污染它們的代碼;
- 所以菜循,當(dāng)編寫工具時(shí)翘地,babel更推薦我們使用一個(gè)插件: @babel/plugin-transform-runtime來完成polyfill的功能
安裝
yarn add install @babel/plugin-transform-runtime -D
使用plugins來配置babel.config.js:
注意:因?yàn)槲覀兪褂昧薱orejs3,所以我們需要安裝對(duì)應(yīng)的庫:
module.exports = {
presets: [
['@babel/preset-env', {
// useBuiltIns: 'entry',
// corejs: 3
}]
],
plugins: [
['@babel/plugin-transform-runtime', {
corejs: 3
}]
]
}
7 React的jsx支持
在我們編寫react代碼時(shí)癌幕,react使用的語法是jsx衙耕,jsx是可以直接使用babel來轉(zhuǎn)換的。
對(duì)react jsx代碼進(jìn)行處理需要如下的插件:
- @babel/plugin-syntax-jsx
- @babel/plugin-transform-react-jsx
- @babel/plugin-transform-react-display-name
但是開發(fā)中勺远,我們并不需要一個(gè)個(gè)去安裝這些插件橙喘,我們依然可以使用preset來配置:
yarn add @babel/preset-react -D
babel.config.js
module.exports = {
presets: [
['@babel/preset-env', {
useBuiltIns: 'entry',
corejs: 3
}],
['@babel/preset-react']
],
}
8 TypeScript
在項(xiàng)目開發(fā)中,我們會(huì)使用TypeScript來開發(fā)胶逢,那么TypeScript代碼是需要轉(zhuǎn)換成JavaScript代碼厅瞎。
8.1 TypeScript的命令行使用
可以通過TypeScript的compiler來轉(zhuǎn)換成JavaScript:
npm install typescript -g
另外TypeScript的編譯配置信息我們通常會(huì)編寫一個(gè)tsconfig.json文件:
tsc --init
之后我們可以運(yùn)行 npx tsc來編譯自己的ts代碼
tsc ./index.ts
8.2 使用ts-loader
如果我們希望在webpack中使用TypeScript饰潜,那么我們可以使用ts-loader來處理ts文件:
yarn add ts-loader -D
配置ts-loader:
webpack.config.js
module.exports = {
module: {
rules: [
test: /\.ts$/,
exclude: /node_modules/,
use: 'ts-loader'
}
]
}
}
8.3 使用babel-loader
除了可以使用TypeScript Compiler來編譯TypeScript之外,我們也可以使用Babel:
- Babel是有對(duì)TypeScript進(jìn)行支持和簸;
- 我們可以使用插件: @babel/tranform-typescript彭雾;
- 但是更推薦直接使用preset:@babel/preset-typescript;
我們來安裝@babel/preset-typescript:
yarn add @babel/preset-typescript -D
webpack.config.js
module.exports = {
entry: './src/main.ts', // ts入口文件
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: 'babel-loader'
}
]
}
}
babel.config.js
module.exports = {
presets: [
['@babel/preset-env', {
useBuiltIns: 'usage',
corejs: 3
}],
['@babel/preset-typescript']
],
}
8.4 ts-loader和babel-loader選擇
那么我們?cè)陂_發(fā)中應(yīng)該選擇ts-loader還是babel-loader呢锁保?
使用ts-loader(TypeScript Compiler)
- 來直接編譯TypeScript冠跷,那么只能將ts轉(zhuǎn)換成js;
- 如果我們還希望在這個(gè)過程中添加對(duì)應(yīng)的polyfill身诺,那么ts-loader是無能為力的;
- 我們需要借助于babel來完成polyfill的填充功能抄囚;
使用babel-loader(Babel)
- 來直接編譯TypeScript霉赡,也可以將ts轉(zhuǎn)換成js,并且可以實(shí)現(xiàn)polyfill的功能幔托;
- 但是babel-loader在編譯的過程中穴亏,不會(huì)對(duì)類型錯(cuò)誤進(jìn)行檢測(cè);
那么在開發(fā)中重挑,我們?nèi)绾慰梢酝瑫r(shí)保證兩個(gè)情況都沒有問題呢嗓化?
8.5 編譯TypeScript最佳實(shí)踐
事實(shí)上TypeScript官方文檔有對(duì)其進(jìn)行說明:
也就是說我們使用Babel來完成代碼的轉(zhuǎn)換,使用tsc來進(jìn)行類型的檢查谬哀。
但是刺覆,如何可以使用tsc來進(jìn)行類型的檢查呢?
- 在這里史煎,我在scripts中添加了兩個(gè)腳本谦屑,用于類型檢查;
- 我們執(zhí)行 npm run type-check可以對(duì)ts代碼的類型進(jìn)行檢測(cè)篇梭;
- 我們執(zhí)行 npm run type-check-watch可以實(shí)時(shí)的檢測(cè)類型錯(cuò)誤氢橙;
package.json
{
"scripts": {
"build": "webpack --config wk.config.js",
"type-check": "tsc --noEmit",
"type-check-watch": "tsc --noEmit --watch"
}
}
*注意:必須有tsconfig.json
文件
9 es-lint
ESLint是一個(gè)靜態(tài)代碼分析工具(Static program analysis,在沒有任何程序執(zhí)行的情況下恬偷,對(duì)代碼進(jìn)行分析)悍手,ESLint可以幫助我們?cè)陧?xiàng)目中建立統(tǒng)一的團(tuán)隊(duì)代碼規(guī)范,保持正確袍患、統(tǒng)一的代碼風(fēng)格坦康,提高代碼的可讀性、可維護(hù)性协怒;并且ESLint的規(guī)則是可配置的涝焙,我們可以自定義屬于自己的規(guī)則;早期還有一些其他的工具孕暇,比如JSLint仑撞、JSHint赤兴、JSCS等,目前使用最多的是ESLint隧哮。
9.1 使用ESLint
安裝
yarn add eslint -D
創(chuàng)建ESLint的配置文件:
npx eslint --init
執(zhí)行檢測(cè)命令:
npx eslint ./src/main.js
9.2 ESLint的配置文件解析
默認(rèn)創(chuàng)建的環(huán)境如下:
- env:運(yùn)行的環(huán)境桶良,比如是瀏覽器,并且我們會(huì)使用es2021(對(duì)應(yīng)的ecmaVersion是12)的語法沮翔;
- extends:可以擴(kuò)展當(dāng)前的配置陨帆,讓其繼承自其他的配置信息,可以跟字符串或者數(shù)組(多個(gè))采蚀;
- parserOptions:這里可以指定ESMAScript的版本疲牵、sourceType的類型
- parser:默認(rèn)情況下是espree(也是一個(gè)JS Parser,用于ESLint)榆鼠,但是因?yàn)槲覀冃枰幾gTypeScript纲爸,所以需要指定對(duì)應(yīng)的解釋器;
- plugins:指定我們用到的插件妆够;
- rules:自定義的一些規(guī)則识啦;
module.exports = {
env: {
browser: true,
commonjs: true,
es2021: true,
},
extends: ['plugin:vue/essential', 'airbnb-base'],
parserOptions: {
ecmaVersion: 12,
parser: '@typescript-eslint/parser',
},
plugins: ['vue', '@typescript-eslint'],
rules: {
// 0 => off
// 1 => warn
// 2 => error
'no-unused-vars': 0,
quotes: ['warn', 'single'],
'no-console': 0,
'import/no-extraneous-dependencies': 0,
},
};
9.3 eslint-loader
安裝
yarn add eslint-loader -D
配置
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: ['babel-loader', 'eslint-loader'],
}
],
},
};
配置完成后,執(zhí)行yarn build
的時(shí)候如果有eslint錯(cuò)誤就會(huì)拋出神妹,阻止打包颓哮。
9.4 vscode插件eslint
但是如果每次校驗(yàn)時(shí),都需要執(zhí)行一次npm run eslint就有點(diǎn)麻煩了鸵荠,所以我們可以使用一個(gè)VSCode的插件:ESLint
9.5 VSCode的Prettier插件
ESLint會(huì)幫助我們提示錯(cuò)誤(或者警告)冕茅,但是不會(huì)幫助我們自動(dòng)修復(fù),在開發(fā)中我們希望文件在保存時(shí)蛹找,可以自動(dòng)修復(fù)這些問題嵌赠;我們可以選擇使用另外一個(gè)工具:prettier
10 加載Vue文件
安裝vue
yarn add vue
安裝相關(guān)依賴
yarn add vue-loader vue-template-compiler -D
配置
webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
module: {
rules: [
{
test: /\.less$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
importLoaders: 2
}
},
"postcss-loader",
"less-loader"
]
},
{
test: /\.vue$/,
use: "vue-loader"
}
],
},
plugins: [
new VueLoaderPlugin()
],
};