源碼地址:https://github.com/h2huanghui/WEBPACK-BASE
一葵蒂、概念
webpack 是一個(gè)現(xiàn)代 JavaScript 應(yīng)用程序的靜態(tài)模塊打包器(module bundler)。當(dāng) webpack 處理應(yīng)用程序時(shí)重虑,它會(huì)遞歸地構(gòu)建一個(gè)依賴關(guān)系圖(dependency graph)践付,其中包含應(yīng)用程序需要的每個(gè)模塊,然后將所有這些模塊打包成一個(gè)或多個(gè) bundle缺厉。
1. 使用Webpack作為前端構(gòu)建工具
- 代碼轉(zhuǎn)換:TS->JS,SCSS->CSS
- 文件優(yōu)化:壓縮JS永高、CSS(加前綴)隧土、HTML代碼,壓縮合并圖片
- 代碼分割:提取多個(gè)頁面的公共代碼命爬、提取首屏不需要執(zhí)行部分的代碼讓其異步加載
- 模塊合并:在采用模塊化的項(xiàng)目里會(huì)有很多個(gè)模塊和文件曹傀,需要構(gòu)建功能把模塊分類合并成一個(gè)文件
- 自動(dòng)刷新:監(jiān)聽本地源代碼的變化,自動(dòng)重新構(gòu)建饲宛、刷新瀏覽器
- 代碼校驗(yàn):在代碼被提交到倉庫前需要校驗(yàn)代碼是否符合規(guī)范皆愉,以及單元測試是否通過(eslint..)
- 自動(dòng)發(fā)布:更新完代碼后,自動(dòng)構(gòu)建出線上發(fā)布代碼并傳輸給發(fā)布系統(tǒng)
2. webpack兩個(gè)核心
- 模塊轉(zhuǎn)換器(loader):用于把模塊原內(nèi)容按照需求轉(zhuǎn)換成新內(nèi)容落萎,可以加載非JS模塊
- 擴(kuò)展插件(plugin):在Webpack構(gòu)建流程中的特定時(shí)機(jī)注入擴(kuò)展邏輯來改變擴(kuò)展結(jié)果或做你想要做的事情(比如先刪除文件夾下的文件,再重新生成)
二亥啦、使用
1. 初始化package.json
npm init -y
2. 安裝webpack webpack-cli
webpack-cli:可以解析用戶傳入的參數(shù),把解析好的參數(shù)傳給webpack進(jìn)行打包(webpack4)
npm install webpack webpack-cli --save-dev
表示開發(fā)環(huán)境
3. 項(xiàng)目目錄下,建立src
文件夾,src
下新建a-module.js
练链,index.js
webpack默認(rèn)支持模塊的寫法 commonjs 規(guī)范翔脱,es6(esmodule)
a-module.js
代碼如下:
module.exports = 'come on,SmartHui'
index.js代碼如下:
let result = require('./a-module')
console.log(result)
node環(huán)境下可以運(yùn)行,但是瀏覽器是不支持這種語法的媒鼓,所以需要把模塊打包届吁,解析出瀏覽器可以識別的代碼
4. 利用webpack webpack-cli 零配置的方式來打包(默認(rèn)去找當(dāng)前文件夾src下的index.js)
npx webpack //npx是npm 5.2之后出來的,幫助執(zhí)行node_modules下的某個(gè)文件
執(zhí)行完之后绿鸣,可以看到生成了一個(gè)dist文件夾疚沐,下面有一個(gè)main.js文件(就是打包之后的結(jié)果,瀏覽器可以識別)
5. 驗(yàn)證打包后的main.js
在dist
文件夾下新建index.html
潮模,引入main.js<script src="./main.js"></script>
亮蛔,在瀏覽器中訪問index.html校读,即可看到控制臺輸出
6. 不建議直接使用npx webpack司倚,vscode可以看到警告
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option
to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
可以 npx webpack --mode development //傳參(webpack-cli會(huì)解析參數(shù))
開發(fā)環(huán)境(development
)打包出來的main.js是默認(rèn)不會(huì)被壓縮的,生產(chǎn)環(huán)境(production
)打包出來的main.js是被壓縮的
7. 每次敲命令會(huì)很麻煩榆纽,把命令配置到package.json中,
"scripts": {
"dev":"webpack --mode development",
"build":"webpack --mode production",
},
運(yùn)行命令npm run dev
,運(yùn)行命令時(shí)动遭,會(huì)把node_modules
下的bin
目錄放到全局上(就會(huì)有.bin
下的命令芬探,執(zhí)行結(jié)束后銷毀)
8. 上述方法比較局限,自己建配置文件配置webpack.config.js
(零配置限制:入口文件只能是src下的index.js,打包也是dist下面的main.js,不好改)
const path = require('path')
module.exports = {
mode:'development', //當(dāng)前是開發(fā)模式
//入口 出口
entry:path.resolve(__dirname,'./src/index.js'), //寫路徑采用絕對路徑(_dirname指的是根目錄)厘惦,防止文件夾變動(dòng)后偷仿,需要重新更改路徑
output: { //出口配置
filename:'bundle.js',
path:path.resolve(__dirname,'dist') //把當(dāng)前bundle放到dist文件夾下(沒有dist文件夾會(huì)自動(dòng)創(chuàng)建)
}
}
可以看到dist
文件夾下,生成了bundle.js宵蕉,并且可以看到文件以及大小
D:\frontEnd\WEBPACK-ALL\WEBPACK-BASE>npm run dev
> WEBPACK-BASE@1.0.0 dev D:\frontEnd\WEBPACK-ALL\WEBPACK-BASE
> webpack --mode development
Hash: 03d09b5e51a493b9408c
Version: webpack 4.41.2
Time: 109ms
Built at: 2019-11-06 11:07:46
Asset Size Chunks Chunk Names
bundle.js 4.17 KiB main [emitted] main
Entrypoint main = bundle.js
[./src/a-module.js] 35 bytes {main} [built]
[./src/index.js] 55 bytes {main} [built]
9. webpack.config.js中傳入mode參數(shù)酝静,修改package.json,去除命令中參數(shù)中的傳遞
"scripts": {
"dev":"webpack",
"build":"webpack"
},
直接運(yùn)行npm run dev
還是ok的
10. 通過vue-cli
create-react-app
源碼羡玛,有自己的webpack
配置形入, 不會(huì)把所有的配置寫到一個(gè)文件里面,都是多個(gè)
配置文件缝左。所以下面進(jìn)行配置文件的拆分
11. 修改package.json
亿遂,給env自掛屬性(development production),這樣在配置文件中可以獲取到當(dāng)前是哪個(gè)環(huán)境
"scripts": {
"dev":"webpack --env.development",
"build":"webpack --env.production"
},
webpack.config.js不僅可以導(dǎo)出一個(gè)對象浓若,也可以導(dǎo)出一個(gè)函數(shù)
module.exports = (env) =>{
console.log(env) //環(huán)境變量 {development:true}
}
npm run dev
可以看到結(jié)果
{ development: true }
Hash: 6c637f5819123099586e
Version: webpack 4.41.2
Time: 131ms
Built at: 2019-11-06 11:31:52
Asset Size Chunks Chunk Names
main.js 1000 bytes 0 [emitted] main
Entrypoint main = main.js
[0] ./src/index.js 55 bytes {0} [built]
[1] ./src/a-module.js 35 bytes {0} [built]
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
所以可以在代碼中判斷當(dāng)前是開發(fā)還是生產(chǎn)
12. 建立build文件夾,下面建立三個(gè)文件蛇数,分別為:webpack.base.js(基本挪钓、公共配置) webpack.dev.js(開發(fā)) webpack.prod.js(生產(chǎn)) 更加清晰,如下圖:
13. 默認(rèn)是找webpack.config.js,所以需要告知wepack去找對應(yīng)的配置文件
"scripts": {
"dev":"webpack --env.development --config ./build/webpack.base.js",
"build":"webpack --env.production ./build/webpack.base.js"
},
這里有兩種方式耳舅,如下碌上,我采用的是1
1. webpack.base.js(傳入?yún)?shù)mode,再根據(jù)env.development去判斷合并webpack.dev.js還是合并webpack.prod.js并返回)
2. 同樣也可以直接指定dev找webpack.dev.js build找webpack.prod.js dev和prod引入base
運(yùn)行npm run dev
,可以看到
{ development: true }
運(yùn)行npm run build
浦徊,可以看到
{ production: true }
14. webpack合并npm i webpack-merge --D
15. webpack.base.js
const dev = require('./webpack.dev')
const prod = require('./webpack.prod')
const path = require('path')
const merge = require('webpack-merge')
module.exports = (env) => { //env是環(huán)境變量
console.log(env)
let isDev = env.development
const base = {
entry: path.resolve(__dirname, '../src/index.js'),
output: {
filename: 'bundle.js',
path: path.resolve(__dirname,'../dist')
}
}
//函數(shù)返回配置文件,沒返回會(huì)采用默認(rèn)配置
if (isDev) {
return merge(base,dev)
} else {
return merge(base,prod)
}
}
webpack.dev.js
module.exports = {
mode:'development'
}
webpack.prod.js
module.exports = {
mode:'production'
}
16. 如果是開發(fā)環(huán)境馏予,要使用webpack-dev-server npm i webpack-dev-server --save-dev
webpack-dev-server是在內(nèi)存中打包的,不會(huì)產(chǎn)生實(shí)體文件
修改package.json
:
- 增加
dev:build
,在開發(fā)環(huán)境看打包后的結(jié)果 - 把webpack修改為webpack-dev-server盔性,就會(huì)啟動(dòng)一個(gè)服務(wù)
"scripts": {
"dev:build": "webpack --env.development --config ./build/webpack.base.js",
"dev": "webpack-dev-server --env.development --config ./build/webpack.base.js",
"build": "webpack --env.production --config ./build/webpack.base.js"
},
如下:
i ?wds?: Project is running at http://localhost:8080/
i ?wds?: webpack output is served from /
i ?wds?: Content not from webpack is served from D:\frontEnd\WEBPACK-ALL\WEBPACK-BASE
i ?wdm?: Hash: 9a936290a170bf8cc970
Version: webpack 4.41.2
運(yùn)行npm run dev
霞丧,可以看到,輸出的文件應(yīng)該在當(dāng)前根目錄,但是當(dāng)我們訪問http://localhost:8080/
并沒有看到bundle.js
而直接訪問 [http://localhost:8080/bundle.js](http://localhost:8080/bundle.js)
,可以看到bundle.js
(從而驗(yàn)證了webpack-dev-server是在內(nèi)存中打包的冕香,不會(huì)產(chǎn)生實(shí)體文件
)
17. 存在問題:端口號是寫死的
修改webpack.dev.js
增加devServer
const path = require('path')
module.exports = {
mode: 'development',
devServer: {
port: 3000,
compress: true,//gzip 可以提升返回頁面的速度
contentBase: path.resolve(__dirname,'../dist') //webpack啟動(dòng)服務(wù)會(huì)在dist目錄下
}
}
運(yùn)行npm run dev
蛹尝,可以看到,運(yùn)行的是index.html(之前手動(dòng)在dist目錄下創(chuàng)建的)
,而且和我們打包生成的bundle.js并沒有什么關(guān)聯(lián)
18. 自動(dòng)生成html文件,并且引入打包后的js
新建public
文件夾,新建 index.html
文件 (作為模板)
19. 配置一個(gè)插件,在打包結(jié)束后,把當(dāng)前文件的資源 打包后的結(jié)果 引入進(jìn)來 并且產(chǎn)生到當(dāng)前dist目錄下npm i html-webpack-plugin --D
修改webpack.base.js
悉尾,引入html-webpack-plugin
插件突那,增加pulgins
配置
const dev = require('./webpack.dev')
const prod = require('./webpack.prod')
const path = require('path')
const merge = require('webpack-merge')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = (env) => { //env是環(huán)境變量
console.log(env)
let isDev = env.development
const base = {
entry: path.resolve(__dirname, '../src/index.js'),
output: {
filename: 'bundle.js',
path: path.resolve(__dirname,'../dist')
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.html'),
filename:'index.html'
})
]
}
//函數(shù)返回配置文件,沒返回會(huì)采用默認(rèn)配置
if (isDev) {
return merge(base,dev) //循環(huán)后面的配置,定義到前面去
} else {
return merge(base,prod)
}
}
運(yùn)行npm run dev
,可以看到(打包在內(nèi)存中构眯,沒有產(chǎn)生實(shí)體文件愕难,所以看不到)
i ?wds?: Project is running at http://localhost:3001/
i ?wds?: webpack output is served from /
i ?wds?: Content not from webpack is served from D:\frontEnd\WEBPACK-ALL\WEBPACK-BASE\dist
i ?wdm?: Hash: 40f577fce1560dc91faf
Version: webpack 4.41.2
打開[http://localhost:3001/](http://localhost:3001/)
,可以看到,index.html中引入了bundle.js
如果要看的打包后的文件惫霸,運(yùn)行npm run build
20. 優(yōu)化打包后的結(jié)果
修改webpack.base.js
中plugins
配置
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.html'),
filename: 'index.html',
minify: !isDev && {
removeAttributeQuotes: true,//移除引號
collapseWhitespace:true //打包為一行
}
})
]
運(yùn)行npm run build
务漩,可以看到實(shí)際結(jié)果
21. 每次打包需要手動(dòng)刪除dist文件夾下的內(nèi)容(原來dist下面有a.js和b.js,重新打包后文件還在它褪,需要手動(dòng)刪除)
npm i clean-webpack-plugin --D
修改webpack.prod.js
,生成環(huán)境
每次都刪除重新生成
const { CleanWebpackPlugin } = require('clean-webpack-plugin') //默認(rèn)導(dǎo)出的是一個(gè)對象,對象有這個(gè)屬性
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns:['**/*'] //默認(rèn)所有目錄下的所有文件
})
所以可以直接寫成
new CleanWebpackPlugin()
補(bǔ)充插件用法:[https://www.npmjs.com/](https://www.npmjs.com/)
22. css文件問題
src
文件夾下翘悉,新建index.css
body {
background: #f0f0f0;
}
index.js
中引入 index.css
import './index.css'
可以看到報(bào)錯(cuò)(需要一個(gè)合適的loader去處理這個(gè)文件類型
)
ERROR in ./src/index.css 1:5
Module parse failed: Unexpected token (1:5)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> body {
| background: #f0f0f0;
| }
@ ./src/index.js 1:0-20
23. 解析CSS茫打,需要兩個(gè)loader(css-loader style-loader)
css-loader
: 解析css語法
style-loader
:會(huì)將解析的css,變成style標(biāo)簽插入到頁面中
npm i css-loader style-loader --D
loader執(zhí)行順序 默認(rèn)是從下往上妖混,從右往左
(loader可以是''
{}
[]
)
字符串格式(從下往上)
module: {
rules: [
{
test: /\.css$/,
use: 'style-loader'
},
{
test: /\.css$/,
use: 'css-loader'
}
]
},
數(shù)組格式(從右往左) --這種方式比較常用
module: {
rules: [
{
test: /\.css$/,
use:['style-loader','css-loader']
}
]
},
運(yùn)行npm run dev
老赤,如圖,可以看到生成了style標(biāo)簽
24. 預(yù)處理器
文件 需要的loader
.scss node-sass sass-loader
.less less less-loader
.stylus stylus stylus-loader
25. 解析scss
npm i node-sass sass-loader --D
node-sass 匹配到scss文件,用sass-loader調(diào)用node-sass解析sass文件
{
test: /\.scss$/,
use:['style-loader','css-loader','sass-loader']
}
26. 存在一個(gè)場景(有bug) index.js引入index.css,index.css中引入a.css,而a.css中又引入了a.scss
webpack首先找到index.js,然后發(fā)現(xiàn)這個(gè)文件里面引入了css文件,所以會(huì)調(diào)用css-loader
來解析制市。但不會(huì)再去解析scss文件(可以看到整個(gè)scss文件直接被插入到style標(biāo)簽中了,而沒有解析去解析,而事實(shí)上,我們是希望去解析的)
index.js
中引入index.css
import './index.css'
index.css
中引入a.css
@import './a.css';
body {
background: #f0f0f0;
}
a.css
中引入a.scss
@import './a.scss'
a.scss
$background: black;
div {
width: 100px;
height: 100px;
background: $background;
}
運(yùn)行npm run dev
,結(jié)果如下:
可以看到抬旺,
a.scss
中的內(nèi)容直接被插入到style標(biāo)簽中了,解析到 a.css
就不會(huì)再去解析里面的引入的 a.scss
了祥楣,但實(shí)際我們希望去解析的
解決方案:給css-loader傳參數(shù)
{
test: /\.css$/,
use: ['style-loader', {
loader: 'css-loader',
options: { //給loader傳遞參數(shù),css文件引入了其他文件,你從當(dāng)前這個(gè)loader之后執(zhí)行這個(gè)文件(先調(diào)用sass-loader,再調(diào)用css-loader) 如果寫2 就是調(diào)用后面兩個(gè)(可以寫多,不可以寫少)
importLoaders:1
}
},'sass-loader']
},
27. 打包c(diǎn)ss還需要處理樣式前綴(比如樣式 transform:rotate(45deg))
在瀏覽器版本比較低是,需要加上webkit前綴
解決方案 npm i postcss-loader --D
同樣也需要一個(gè)插件 (就像sass-loader會(huì)調(diào)用node-sass)
npm i autoprefixer --D
{
test: /\.css$/,
use: ['style-loader', {
loader: 'css-loader',
options: { //給loader傳遞參數(shù),css文件引入了其他文件,你從當(dāng)前這個(gè)loader之后執(zhí)行這個(gè)文件(先調(diào)用sass-loader,再調(diào)用css-loader) 如果寫2 就是調(diào)用后面兩個(gè)(可以寫多,不可以寫少)
importLoaders:2
}
},'postcss-loader','sass-loader']
},
postcss-loader
需要一個(gè)配置文件postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')
]
}
28. 存在問題:打包后的bundle.js中并沒有加上前綴(目前瀏覽器默認(rèn)版本都比較高,加了有些浪費(fèi)性能)
解決方案 告訴當(dāng)前瀏覽器(參考[https://github.com/browserslist/browserslist](https://github.com/browserslist/browserslist) )
- .browserslistrc
cover 95%
- package.json
"browserslist": [
"defaults",
"not ie < 9",
"last 2 versions",
"> 1%",
"iOS 7",
"last 3 iOS versions"
],
選擇其中一個(gè)即可
开财,這里選擇的是方法1
汉柒,運(yùn)行npm run dev:build
,bundle.js
如下:
29. 這種方法解析css的時(shí)候责鳍,不能渲染dom碾褂。但是我們希望css和js一同并行加載,所以我們需要抽離css文件历葛。
抽離css插件 npm i mini-css-extract-plugin --D
開發(fā)環(huán)境不用抽取,線上環(huán)境需要抽取
{
test: /\.css$/,
use: [
isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 2
}
}, 'postcss-loader', 'sass-loader']
},
30. 告訴webpack抽取出來的css叫什么
plugins: [
!isDev && new MiniCssExtractPlugin({
filename:'css/main.css'
}),
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.html'),
filename: 'index.html',
minify: !isDev && {
removeAttributeQuotes: true,//移除引號
collapseWhitespace: true //打包為一行
}
})
].filter(Boolean)
補(bǔ)充知識點(diǎn)
:
[].filer(Boolean)等價(jià)于 [簡寫模式]
[].filter((x)=>{
return Boolean(x)
})
把plugins里面的每一項(xiàng)處理正塌,把結(jié)果為false的過濾掉
執(zhí)行npm run build
,發(fā)現(xiàn)dist目錄下多了css/main.css
31. 存在問題:css文件未壓縮
-
webpack
生產(chǎn)環(huán)境只會(huì)默認(rèn)壓縮js
,css
不會(huì)壓縮,需要另外配置npm i optimize-css-assets-webpack-plugin --save-dev
- 如果
css
手動(dòng)壓縮,那么js也需要手動(dòng)壓縮npm i terser-webpack-plugin --save-dev
const TerserWebpackPlugin = require('terser-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = {
mode: 'production',
optimization: { //優(yōu)化項(xiàng)
minimizer: [
new TerserWebpackPlugin(), //css手動(dòng)壓縮的話 js也需要手動(dòng)壓縮
new OptimizeCSSAssetsPlugin() //css壓縮
]
}
}
運(yùn)行npm run build
,可以看到css
和js
均被壓縮
32. 圖片
src
下放一張logo.jpg
圖片
編輯 index.js
代碼
//獲取當(dāng)前打包logo后的路徑
import logo from './logo.jpg'
console.log(logo)
let img = document.createElement('img')
img.src = logo
document.body.appendChild(img)
運(yùn)行npm run dev
恤溶,報(bào)錯(cuò)不認(rèn)識圖片
需要安裝file-loader
(默認(rèn)功能拷貝乓诽,拷貝到dist目錄下,并且返回圖片)npm i file-loader -D
{
test: /.jpe?g|png|gif$/,
use:'file-loader'
}
運(yùn)行npm run build
咒程,結(jié)果如下:
34. 小圖片轉(zhuǎn)成base64(編碼比以前大,不用發(fā)送http請求)
npm i url-loader -D
{
//圖片轉(zhuǎn)換
test: /\.(jpe?g|png|gif)$/,
use: {
loader: 'url-loader',
//如果小于100k鸠天,會(huì)使用url-loader
//如果大于100k,會(huì)使用file-loader
options: {
name:'image/[contentHash].[ext]', // 打包后的圖片目錄(當(dāng)前contentHash-圖片打包后的hash ext-當(dāng)前后綴)
limit: 100*1024
}//file-loader 默認(rèn)的功能是拷貝的作用
//希望當(dāng)前較小的圖片可以轉(zhuǎn)化成base64 比以前大 好處就是不用http請求
}
}
運(yùn)行npm run build
,結(jié)果如下孵坚,可以對比看到粮宛,打包后的差別
- 使用
url-loader
,打包后無img卖宠,并且bundle.js文件大小變大了
35. 圖標(biāo)
{ //圖標(biāo)轉(zhuǎn)換
test: /\.(woff|ttf|eot|svg)$/,
use:'file-loader'
},
36. js轉(zhuǎn)換
npm i @babel/core @babel/preset-env babel-loader -D
- babel/core: 核心模塊
- babel/preset-env: 插件集合(所有將es6->es5的插件)
- babel-loader: webpack使用的loader
關(guān)系:默認(rèn)會(huì)調(diào)用babel/core會(huì)轉(zhuǎn)化代碼 轉(zhuǎn)化的時(shí)候需要@babel/presets-env 將es6轉(zhuǎn)換成es5
@
是指作用域巍杈,npm
之后把所有babel相關(guān)的都放在一個(gè)目錄下,如圖:
修改index.js
//es6->es5
const fn = () => {
}
fn()
配置webpack.base.js
扛伍,把具體的配置寫在options
中
{//解析js文件 默認(rèn)會(huì)用調(diào)用@babel/core
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
}
}
}
如果options很多的話不方面,所以建一個(gè)配置文件.babelrc
{
test: /\.js$/,
use: 'babel-loader'
},
插件的集合
.babelrc
{
//preset從下往上執(zhí)行
"presets": [
"@babel/preset-env"
],
//plugins從上往下執(zhí)行
"plugins":[
]
}
執(zhí)行npm run dev:build
筷畦,如圖,可以看到代碼成功轉(zhuǎn)換
37. js草案語法
class A {
a = 1 //實(shí)例上的屬性,并且是私有的
}
等同于
class A{
constructor() {
this.a = 1
}
}
運(yùn)行npm run dev:build
刺洒,報(bào)錯(cuò)如圖
安裝報(bào)錯(cuò)中所需要的插件 npm i @babel/plugin-proposal-class-properties --save-dev
修改.babelrc
- presets:插件集合
- plugin: 單個(gè)插件
{
"presets": [
"@babel/preset-env"
],
"plugins":[
["@babel/plugin-proposal-class-properties", {
"loose": true
}]
]
}
執(zhí)行npm run dev:build
修改.babelrc
,"loose":false
一般情況是用"loose":true
鳖宾,因?yàn)檫@樣可以用裝飾器
38. es7 裝飾器
修改 index.js
,target
代表的就是A
@log
class A {
a = 1 //實(shí)例上的屬性,并且是私有的
}
function log(target) {
console.log(target)
}
執(zhí)行npm run dev
,報(bào)錯(cuò)
訪問[https://babeljs.io/](https://babeljs.io/)
逆航,搜索decorators
https://babeljs.io/docs/en/babel-plugin-proposal-decorators鼎文,根據(jù)文檔配置即可
首先,npm install --save-dev @babel/plugin-proposal-decorators
其次因俐,修改.babelrc
{
"presets": [
"@babel/preset-env"
],
"plugins":[
["@babel/plugin-proposal-decorators", {
"legacy": true
}],
["@babel/plugin-proposal-class-properties", {
"loose": true
}]
]
}
執(zhí)行npm run dev:build
拇惋,如圖:
可以看到,A作為target傳入log函數(shù)
直接在node
環(huán)境運(yùn)行抹剩,可以看到打印出來的target
39. api自動(dòng)轉(zhuǎn)換
修改index.js
[1, 2, 3].includes(1);
執(zhí)行npm run dev:build
可以看到撑帖,并未進(jìn)行轉(zhuǎn)化,這是因?yàn)槟J(rèn)
不能轉(zhuǎn)換高級語法,實(shí)例上的語法以及promise
澳眷,所以我們需要自己進(jìn)行手動(dòng)配置
修改.babelrc
{
"presets": [
["@babel/preset-env",{
"useBuiltIns": "usage" //使用的api 會(huì)自動(dòng)轉(zhuǎn)化,并且是按需加載
}]
],
"plugins":[
["@babel/plugin-proposal-decorators", {
"legacy": true
}],
["@babel/plugin-proposal-class-properties", {
"loose": true
}]
]
}
執(zhí)行npm run dev:build
,報(bào)錯(cuò)了
原因就是胡嘿,遇到
includes
,不知道是引入string.includes
還是array.includes
按照報(bào)錯(cuò)的提示钳踊,我們安裝code.js
npm install --save-dev core-js@2
(這里我們用2)
-
code.js
類似于babel-polyfill
修改.babelrc
{
"presets": [
["@babel/preset-env",{
"useBuiltIns": "usage",
"corejs": 2
}]
],
"plugins":[
//解析裝飾器
["@babel/plugin-proposal-decorators", {
"legacy": true
}],
//解析類的屬性
["@babel/plugin-proposal-class-properties", {
"loose": true
}]
]
}
運(yùn)行npm run dev:build
,成功編譯
40. babel7新特性:解決重復(fù)引入_classCallCheck
修改index.js
import './a'
class A {
}
a.js
中也有一個(gè)class
class B {
}
執(zhí)行npm run dev:build
可以看到衷敌,引入了兩次_classCallCheck(代碼冗余)
解決辦法npm install --save-dev @babel/plugin-transform-runtime
節(jié)約代碼
https://babeljs.io/docs/en/babel-plugin-transform-runtime#docsNav
參考文檔勿侯,還需要安裝npm install --save @babel/runtime
(線上需要使用)
修改.babelrc
{
"presets": [
["@babel/preset-env",{
"useBuiltIns": "usage",
"corejs": 2
}]
],
"plugins":[
//解析裝飾器
["@babel/plugin-proposal-decorators", {
"legacy": true
}],
//解析類的屬性
["@babel/plugin-proposal-class-properties", {
"loose": true
}],
["@babel/plugin-transform-runtime"]
]
}
執(zhí)行npm run dev:build
可以看到,a.js和index.js中,都使用的一種方法引入_classCallCheck
41. 如何編譯react
安裝npm i react react-dom --save
安裝npm i @babel/preset-react --save-dev
修改index.js
import React from 'react'
import ReactDOM from 'react-dom'
ReactDOM.render(<div>hello</div>,document.getElementById('root'))
修改.babelrc
{
"presets": [
["@babel/preset-env",{
"useBuiltIns": "usage",
"corejs": 2
}],
"@babel/preset-react"
],
"plugins":[
//解析裝飾器
["@babel/plugin-proposal-decorators", {
"legacy": true
}],
//解析類的屬性
["@babel/plugin-proposal-class-properties", {
"loose": true
}],
["@babel/plugin-transform-runtime"]
]
}
運(yùn)行npm run dev
,可以看到成功了
42. ts配置
新建index1.jsx
import React from 'react'
import ReactDOM from 'react-dom'
//ts校驗(yàn)類型
interface IProps {
num: number
}
let initState = { count: 0 }
type State = Readonly<typeof initState>
class Counter extends React.Component<IProps,State> {
state: State = initState
render() {
return(
<div>
{this.state.count}
<button onClick={this.handleClick}>點(diǎn)擊</button>
</div>
)
}
handleClick = () => {
this.setState({
count:this.state.count + 1
})
}
}
ReactDOM.render(<Counter />,document.getElementById('root'))
使用ts有兩種方案:
- 使用ts-loader逢享,需要配合typescript庫使用
- babel7發(fā)明一個(gè)包罐监,專門解析ts
@babel/preset-typescript
npm i @babel/preset-typescript --save-dev
修改webpack.base.js,入口文件應(yīng)該是index.jsx
entry: path.resolve(__dirname, '../src/index.jsx')
并且瞒爬,增加解析ts文件的配置
然后弓柱,修改.babelrc
,先ts->js->react->es5
運(yùn)行npm run dev
,編譯成功
43.解決代碼報(bào)錯(cuò)
用ts去校驗(yàn)代碼,是否符合規(guī)范侧但,是否是ts語法
首先矢空,安裝npm i typescript //并不是用來解析語法,而是用來校驗(yàn)代碼
然后禀横,本地執(zhí)行npx typescript --init
,可以看到本地生成了一個(gè)文件 tsconfig.json
可以看到代碼報(bào)錯(cuò)屁药,react并不是ts版本
根據(jù)提示安裝npm i @types/react @types/react-dom --save
安裝成功后,可以看到報(bào)錯(cuò)(error1)消失
但是柏锄,可以看到代碼還有報(bào)錯(cuò)酿箭,不認(rèn)識JSX,修改tsconfig.json
可以看到報(bào)錯(cuò)(error2)消失
使用Count應(yīng)該傳
num
屬性
修改index.tsx
ReactDOM.render(<Counter num={1} />,document.getElementById('root'))
44. vue配置
新建index.ts
import Vue from 'vue'
let vm = new Vue({
el: '#root',
render: h => h('h1', {}, 'hello vue')
})
修改webpack.base.js
入口
entry: path.resolve(__dirname, '../src/index.ts')
執(zhí)行npm run dev
新建App.vue
<template>
<div>
Welcome
</div>
</template>
修改index.ts
import Vue from 'vue'
import App from './App.vue'
let vm = new Vue({
el: '#root',
render: h => h(App)
})
可以看到報(bào)錯(cuò)
解決方法:新建vue-shims.d.ts
,也是任何.vue文件,都看成一個(gè)Vue類型(名稱隨便趾娃,后綴名一定要是.d.ts
)
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
解析vue
缭嫡,需要安裝npm i vue-loader vue-template-compiler --save-dev
修改webpack.base.js
還需要引入一個(gè)插件
const VueLoaderPlugin = require('vue-loader/lib/plugin')
plugins: [
!isDev && new MiniCssExtractPlugin({
filename:'css/main.css'
}),
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.html'),
filename: 'index.html',
minify: !isDev && {
removeAttributeQuotes: true,//移除引號
collapseWhitespace: true //打包為一行
}
})
].filter(Boolean)
運(yùn)行npm run dev
,成功