一、 Webpack 和打包過(guò)程
編寫(xiě)的代碼 ==》經(jīng)過(guò)打包工具(glup、rollup、webpack、vite)本身也是js代碼,讀取文件操作的,依賴于 node 環(huán)境
= = 》 普通的html 、css 、javascript
= = 》 打包到靜態(tài)服務(wù)器
= = 》 跑在用戶的瀏覽器
1.1 內(nèi)置模塊 path
- 用于對(duì)路徑和文件進(jìn)行處理
- 在 Mac OS、Linux 和 window 上的路徑上是不一樣的,部署的時(shí)候顯示路徑會(huì)出現(xiàn)一些問(wèn)題,為了屏蔽他們之間的差異,在開(kāi)發(fā)中對(duì)于路徑的操作可以使用 path模塊
const path = require("path");
// 幫助我們從路徑當(dāng)中獲取一些信息
const filepath = "C://abc/cba/nba.txt";
// 1. 可以從一個(gè)路徑中獲取一些信息
// 1.1 拿到文件的后綴名
console.log(path.extname(filepath));
// 1.2 獲取文件名
console.log(path.basename(filepath));
// 1.3 獲取文件夾
console.log(path.dirname(filepath));
const path1 = "/abc/cba";
const path2 = "../../lili/kobe/james.txt";
// 2. 將多個(gè)路徑拼接在一起
console.log(path.join(path1, path2));
// 3. 將多個(gè)路徑拼接在一起,最終返回一個(gè)絕對(duì)路徑: path.resolve
console.log("-----resolve------");
// 從右向左依次處理,形成了絕對(duì)路徑就不會(huì)繼續(xù)往前找了
console.log(path.resolve(path1, path2,"/abc.txt"));
1.2 認(rèn)識(shí) webpack
- 隨著前端的快速發(fā)展,目前前端的開(kāi)發(fā)已經(jīng)越來(lái)越復(fù)雜
- 模塊化的方式進(jìn)行開(kāi)發(fā)
- 使用高級(jí)的特性來(lái)加快我們的開(kāi)發(fā)效率或者安全性
- 實(shí)時(shí)監(jiān)聽(tīng)文件的變化,反映到瀏覽器上,提高開(kāi)發(fā)的效率
- 將代碼進(jìn)行壓縮、合并以及其他相關(guān)的優(yōu)化
- 腳手架依賴 webpack
- vue:cli-service
- react:config
- angular
-
webpack is a static module bundler for modern javascript application
- 靜態(tài)的:打包成普通的靜態(tài)文件:html 、 css 、js
- 模塊化:common.js、amd 、cmd、
- 現(xiàn)代的:應(yīng)用程序復(fù)雜,才催生了webpack
- 打包工具:本質(zhì)是幫我們進(jìn)行打包的
1.3 vue 項(xiàng)目加載的文件
- javascript 的打包
- 將 es6 轉(zhuǎn)成es5
- ts 轉(zhuǎn)成 js
- css 的處理
- css 文件模塊的加載、提取
- less、sass 等預(yù)處理器的處理
- 資源文件 img、font
- 字體 font 文件的加載
- 圖片 img 文件的加載
- html 資源的處理
- 打包 html 資源文件
- 處理 vue 項(xiàng)目的 sfc 文件 .vue 文件
1.4 webpack 的使用
- webpack 、webpack-cli
- webpack-cli:識(shí)別命令行
-
局部安裝:
npm i webpack webpack-cli -D
- 使用局部的
npx webpack
后面可以跟參數(shù) - 配置參數(shù)很多,可以寫(xiě)到一個(gè)單獨(dú)的文件里面:
webpack.config.js
– webpack 配置文件
const path = require("path");
module.exports = {
// 配置入口
entry: "./src/index.js",
// 配置出口
output: {
filename: "bundle.js",
// 必須是絕對(duì)路徑
path: path.resolve(__dirname, "./build"),
},
};
1.5 webpack 形成的依賴圖
- 從入口開(kāi)始,會(huì)生成一個(gè)依賴關(guān)系圖,會(huì)包含應(yīng)用程序中所需的所有模塊(.js文件、css文件、圖片、字體)
- 遍歷圖結(jié)構(gòu),打包一個(gè)個(gè)模塊
- 根據(jù)文件的不同使用不同的 loader 來(lái)解析
1.6 loader
- loader
- loader 可以用于對(duì)模塊的源代碼進(jìn)行轉(zhuǎn)換
- 將 css 文件也看成是一個(gè)模塊,通過(guò) import 來(lái)加載這個(gè)模塊
- 在加載這個(gè)模塊的時(shí)候,webpack 其實(shí)并不知道如何進(jìn)行加載,必須制定相應(yīng)的規(guī)則去完成這個(gè)功能
-
配置文件 =》module =》rules
- 匹配 .vue=>使用 vue.loader
- 匹配 .css=>使用 css.loader
- 默認(rèn) webpack 會(huì)處理 js 文件
- 配置方式
- module{}
- rules[]
- {
- test
- use:多個(gè) loader 的使用規(guī)則是從后往前的
- }
- rules[]
- module{}
1.7 css-loader
- 安裝:
npm i css-loader -D
- 配置規(guī)則
module: {
// 規(guī)則很多,對(duì)應(yīng)的是數(shù)組類型
rules: [
// 數(shù)組里面放對(duì)象
{
// 告訴webpack 要匹配什么文件
test: /\.css$/,
// 要使用哪些loader
use: [{ loader: "css-loader" }],
},
],
},
- 只負(fù)責(zé)解析 css 文件,并不負(fù)責(zé)插入到頁(yè)面中
1.8 style-loader
- 插入 style
- 安裝:
npm i style-loader -D
const path = require("path");
module.exports = {
// 配置rukou
entry: "./src/index.js",
// 配置出口
output: {
filename: "bundle.js",
// 必須是絕對(duì)路徑
path: path.resolve(__dirname, "./build"),
},
module: {
// 規(guī)則很多,對(duì)應(yīng)的是數(shù)組類型
rules: [
// 數(shù)組里面放對(duì)象
{
// 告訴webpack 要匹配什么文件
test: /\.css$/,
// 要使用哪些loader
use: [{ loader: "style-loader" }, { loader: "css-loader" }],
},
],
},
};
- 簡(jiǎn)寫(xiě)
test: /\.css$/,
// 要使用哪些loader
// use: [{ loader: "style-loader" }, { loader: "css-loader" }],
// 簡(jiǎn)寫(xiě)一:如果 Loader 只有一個(gè)
// loader: 'css-loader'
// 簡(jiǎn)寫(xiě)二:多個(gè)loader不需要配置其他options
use: ["style-loader", "css-loader"],
1.9 less-loader
- 前提需要安裝 less
- 安裝:
npm i less-loader -D
- 配置
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
1.10 postcss-loader
-
安裝:
npm i postcss-loader -D
-
使用:
use: ["style-loader", "css-loader", "postcss-loader"]
-
postcss 介紹
- 通過(guò) javascript 來(lái)轉(zhuǎn)換樣式的工具
- 這個(gè)工具可以幫助我們進(jìn)行一些 css 的轉(zhuǎn)換和適配,比如自動(dòng)添加瀏覽器前綴、css樣式的重置
- 需要借助 對(duì)應(yīng)的插件
- 安裝:
npm i autoprefixer -D
- 安裝:
-
重新配置
- options 里面添加的東西會(huì)被 loader 讀取
{ // 告訴webpack 要匹配什么文件 test: /\.css$/, use: [ "style-loader", "css-loader", { loader: "postcss-loader", options: { postcssOptions: { plugins: [ "autoprefixer" ] }, }, }, ], },
- 這樣就能實(shí)現(xiàn)添加瀏覽器前綴
-
太臭太長(zhǎng)了,在項(xiàng)目目錄中里面創(chuàng)建文件
postcss.config.js
- 當(dāng)寫(xiě)成簡(jiǎn)寫(xiě)的時(shí)候沒(méi)有配置對(duì)應(yīng)的 options,就會(huì)自己讀取這個(gè)文件
module.exports = { plugins: ["autoprefixer"], };
-
因?yàn)橛邢旅孢@個(gè),所以卸載它:npm uninstall autoprefixer
-
也可以使用另外的插件
postcss-preset-env
:預(yù)設(shè)環(huán)境- 可以將一些現(xiàn)代的 css 特性,轉(zhuǎn)成大多數(shù)瀏覽器認(rèn)識(shí)的 css ,并且會(huì)根據(jù)目標(biāo)瀏覽器或者運(yùn)行時(shí)環(huán)境添加所需的 polyfill
- bgc-color:#666666==》 rgba 的格式
- 包括 autoprefixer
- 安裝:
npm install postcss-preset-env -D
- 可以將一些現(xiàn)代的 css 特性,轉(zhuǎn)成大多數(shù)瀏覽器認(rèn)識(shí)的 css ,并且會(huì)根據(jù)目標(biāo)瀏覽器或者運(yùn)行時(shí)環(huán)境添加所需的 polyfill
1.11 Webpack打包圖片-JS-Vue
- 現(xiàn)代的前端開(kāi)發(fā)模式中,根本不需要手動(dòng)添加瀏覽器前綴
- 引入圖片模塊:
import 圖片名字 from "../img/zznh.png"
- 可以給這個(gè)模塊起一個(gè)名字
- 早期加載資源使用:
npm i file-loader
- 在最新的版本已經(jīng)不用這個(gè)東西了
- webpack5之后使用資源模塊類型開(kāi)替代這些loader
- raw-loader、url-loader、file-loader
{
test: /\.(png|jpe?g|svg|gif)$/,
// 當(dāng)成資源類型
type:"assets"
},
1.12 資源模塊類型
- asset/resource:發(fā)送一個(gè)單獨(dú)的文件并導(dǎo)出 URL
- 缺點(diǎn):多了 http 網(wǎng)絡(luò)請(qǐng)求(幾張圖片就幾次)
- asset**/inline**:導(dǎo)出一個(gè)資源的 data URL
- 優(yōu)點(diǎn):可以少發(fā)送兩次請(qǐng)求
- 缺點(diǎn):造成 js 文件很大,下載 、解析js 文件時(shí)間非常長(zhǎng)
- asset/source:導(dǎo)出資源的源代碼
-
asset
- 使用過(guò)程
- 將 type 改成 asset
- 添加 parser 屬性,并且制定 dataUrl 的條件
- maxSize
- 使用過(guò)程
const { type } = require("os");
const path = require("path");
const { webpack } = require("webpack");
module.exports = {
// 配置rukou
entry: "./src/index.js",
// 配置出口
output: {
filename: "bundle.js",
// 必須是絕對(duì)路徑
path: path.resolve(__dirname, "./build"),
// assetModuleFilename: "abc.png",//很少在這配置
},
module: {
// 規(guī)則很多,對(duì)應(yīng)的是數(shù)組類型
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader", "postcss-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.(png|jpe?g|svg|gif)$/,
// 當(dāng)成資源類型
// type: "asset"
// 1. 打包兩張圖片,并且這兩張圖片有自己的地址,將地址設(shè)置到img/bgi中
// type:"asset/resource"
// 2. 把圖片進(jìn)行 base64 編碼,并且直接將編碼后的源碼放在打包的js文件中
// type: "asset/inline"
// 合理的規(guī)范
// 1 對(duì)于小一點(diǎn)的圖片,可以進(jìn)行base64的編碼
// 2 對(duì)于大一點(diǎn)的圖片,單獨(dú)的圖片打包,形成 url 地址,單獨(dú)的請(qǐng)求這個(gè) url 文件
// 由此誕生了asset
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 60 * 1024,
},
},
// 設(shè)置文件名
generator: {
// 一般名字不寫(xiě)死,寫(xiě)上占位符
// name:指向原來(lái)的圖片名稱
// ext(擴(kuò)展名):直接帶點(diǎn)
// hash:webpack生成的hash,只使用前八位
// 放在build的img 文件夾
filename: "img/[name]_[hash:8][ext]",
},
},
],
},
};
1.13 babel
- 想要使用 ES6+ 的語(yǔ)法,使用 ts ,開(kāi)發(fā) react,都是離不開(kāi) babel 的
- 安裝:
npm i babel-loader -D
{
test: /\.js$/,
use: ["babel-loader"],
},
- babel 是一個(gè)工具鏈,用于舊瀏覽器或者環(huán)境中將 es5 代碼轉(zhuǎn)換為向后兼容版本的 js
- 語(yǔ)法轉(zhuǎn)換:箭頭函數(shù)
- 源代碼轉(zhuǎn)換:對(duì)標(biāo)識(shí)符進(jìn)行轉(zhuǎn)化
- 本身可以作為一個(gè)獨(dú)立的工具,不和webpack等構(gòu)建工具來(lái)單獨(dú)使用
- 命令行使用,需要安裝
- @babel/core:babel 的核心代碼,必須安裝
- @babel/cli:在命令行使用 babel
npm i @babel/cli @babel/core -D
- 安裝插件
- 轉(zhuǎn)換對(duì)應(yīng)的東西
- 每個(gè)插件完成對(duì)應(yīng)的功能
- 單獨(dú)抽取出配置:
babel.config.js
module.exports = {
// plugins: [
// "@babel/transform/"
// ]
presets: ["@babel/preset-env"],
};
- 單獨(dú)配置太麻煩了,安裝預(yù)設(shè):
npm i @babel/preset-env -D
- 常見(jiàn)的預(yù)設(shè)
- env
- react
- TypeScript
- 常見(jiàn)的預(yù)設(shè)
.vue
- 安裝 vue :
npm i vue
開(kāi)發(fā)生產(chǎn)都會(huì)使用 - 安裝loader:
npm i vue-loader -D
{
test: /\.vue$/,
loader:"vue-loader"
}
- vue文件中配置對(duì)應(yīng)的 vue 插件:幫助我們解析 css
const { VueLoaderPlugin } = require('vue-loader/dist/index')
const path = require("path");
const { webpack } = require("webpack");
module.exports = {
// 配置rukou
entry: "./src/index.js",
// 配置出口
output: {
filename: "bundle.js",
// 必須是絕對(duì)路徑
path: path.resolve(__dirname, "./build"),
// assetModuleFilename: "abc.png",//很少在這配置
},
module: {
// 規(guī)則很多,對(duì)應(yīng)的是數(shù)組類型
rules: [
{
test: /\.vue$/,
loader:"vue-loader"
}
],
},
plugins: [
new VueLoaderPlugin()
]
};
1.14 resolve 模塊解析
-
用于設(shè)置模塊如何被解析
- 幫助 webpack 從每個(gè) require/import 語(yǔ)句中,找到需要引入到合適的模塊代碼
-
webpack 能解析三種文件路徑
- 絕對(duì)路徑
- 相對(duì)路徑
- 模塊路徑
- resolve.modules 中指定的所有目錄檢索模塊:默認(rèn)為 node_modules
- 設(shè)置別名
-
解析
-
文件:
imprt utils form './utils/format'
js/json-
具備擴(kuò)展名,直接打包文件
-
否則使用 resolve.extentions 自動(dòng)添加擴(kuò)展名
- 默認(rèn)值是 [‘.wasm’,‘’.mjs’,‘.js’,‘.json’]
-
可以自己配置 resolve
-
resolve: { // 配置后可省略后綴名 extensions:['.js','.json','.vue','.jsx','.ts','.tsx'] },
-
-
文件夾:
- 在文件夾中根據(jù) resolve.mainFiles 配置選項(xiàng)中指定的文件順序查找
- 默認(rèn)值是 [‘index’]
- 再根據(jù) resolve.extentions 來(lái)解析擴(kuò)展名
-
-
alias
- 給文件夾配置別名,解決嵌套層次深的問(wèn)題
resolve: {
// 省略后綴名
extensions: [".js", ".json", ".vue", ".jsx", ".ts", ".tsx"],
// 給文件夾配置別名
alias: {
utils: path.resolve(__dirname, "./src/utils"),
},
},
二、webpack 常見(jiàn)的插件和模式
2.1 plugin
- loader 是用于特定類型的模塊類型進(jìn)行轉(zhuǎn)換
- .vue .css .png
- Plugin 作用廣泛的任務(wù),可以做 loader 之外的所有事情
- 打包優(yōu)化
- 資源管理
- 環(huán)境變量注入
2.2 CleanWebpackPlugin
- 作用:每次修改配置重新打包時(shí)候,不需要手動(dòng)刪除 dist 文件夾
- 安裝這個(gè)插件:
npm i clean-webpack-plugin -D
- 在插件中進(jìn)行配置
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
plugins: [new VueLoaderPlugin(),new CleanWebpackPlugin()],
- 也可以直接在output中將 clear 設(shè)置為true
output: {
filename: "bundle.js",
// 必須是絕對(duì)路徑
path: path.resolve(__dirname, "./build"),
// assetModuleFilename: "abc.png",//很少在這配置
clear: true,
},
2.3 HtmlWebpackPlugin
-
在進(jìn)行項(xiàng)目部署的時(shí),必然也是需要有對(duì)應(yīng)的入口文件 index.html,需要對(duì) index.html 進(jìn)行打包處理
-
安裝這個(gè)插件:
npm i html-webpack-plugin -D
-
build 文件夾下面會(huì)自動(dòng)生成 html 文件
-
在生成過(guò)程會(huì)有一個(gè)模板,在 html-webpack-plugin 的源碼中,有一個(gè) default_index.ejs 模塊
-
也可以自定義模板
const HtmlWebpackPlugin = require("html-webpack-plugin");
plugins: [
new HtmlWebpackPlugin({
title: "實(shí)時(shí)音頻流可視化",
// 自己指定模板
template:'./index.html'
}),
],
2.4 DefinePlugin
-
webpack 中內(nèi)置的插件
-
全局注入變量
-
默認(rèn)注入了變量:
process.env.NODE_ENV
-
可以使用 DefinePlugin 中定義的變量
const { DefinePlugin } = require("webpack");
plugins: [
new DefinePlugin({
// 會(huì)當(dāng)成代碼去解析,所以需要加引號(hào)(eval)
// 前邊是變量,隨便你加不加引號(hào)
BASE_URL: "'./'",
lili: "'lili'",
}),
],
2.5 Mode
- 告訴 webpack目前所處的一個(gè)環(huán)境
- 默認(rèn)值是 production
- 可選值有:
none
|development
|production
- 每一個(gè)模式涉及很多配置
- 配置:
mode:production,
三、Webpack 搭建本地服務(wù)器
3.1 作用
- 修改代碼后自動(dòng)重新打包并且自動(dòng)刷新
- 自動(dòng)重新編譯:
- webpack watch mode:可以自動(dòng)編譯但是不會(huì)自動(dòng)刷新瀏覽器
- webpack-dev-server(常用)
- webpack-dev-middleware
3.2 webpack-dev-server
- 安裝:
npm i webpack-dev-server -D
- 會(huì)搭建一個(gè)本地服務(wù)
- 會(huì)自動(dòng)進(jìn)行打包,但是不會(huì)生成本地的文件,直接放在內(nèi)存里面,直接給你搭建服務(wù)器,從內(nèi)存中讀取
3.3 模塊熱替換 HMR
- 在應(yīng)用程序運(yùn)行過(guò)程中,替換、添加、刪除模塊,而無(wú)需重新刷新整個(gè)頁(yè)面
- 提高開(kāi)發(fā)的速度
- 不重新加載整個(gè)頁(yè)面
- 只更新需要變化的內(nèi)容
- 修改 webpack 的配置,但是還是刷新一整個(gè)頁(yè)面
devServer: {
hot:true
},
-
需要在 main.js 手動(dòng)指定哪些模塊發(fā)生更新時(shí),進(jìn)行HMR
- 先判斷是否開(kāi)啟 HMR
- 再告訴他那個(gè)模塊更新需要發(fā)生替換
if (module.hot) { module.hot.accpet("./utils/math.js", () => { console.log("happen hot gengxin"); }) }
-
框架已經(jīng)集成好了,不需要手動(dòng)配置
## 3.4 host
- 設(shè)置主機(jī)地址,默認(rèn)值是 localhost
- 看 ip 地址:網(wǎng)絡(luò)=》屬性
- 設(shè)置為 0.0.0.0 都可以看到
3.5 open
- true / false : 是否自動(dòng)打開(kāi)瀏覽器
devServer: {
hot: true,
// 端口位置
port: 8888,
// host設(shè)置主機(jī)地址,默認(rèn)值是 localhost
host: '0.0.0.0',
open: ture,
// 自動(dòng)把打包的文件進(jìn)行g(shù)zip壓縮
compress: true
},
3.6 區(qū)分開(kāi)發(fā)環(huán)境和生產(chǎn)環(huán)境
-
打包適用于生產(chǎn)環(huán)境
-
創(chuàng)建 config 文件夾
- webpack.dev.config.js
- webpack.prod.config.js
-
使用 serve / build 是不同的兩套配置
-
context 的作用:解析入口和加載器
- 默認(rèn)路徑是 webpack 的啟動(dòng)路徑(腳本中配置了)
"build": "webpack --config ./config/webpack.prod.config.js", "serve": "webpack serve --config ./config/webpack.dev.config.js"
// 配置入口 // context:'', // 相對(duì)于 context entry: "./src/index.js",
-
很多配置是相似的
- 抽取公共配置:
webpack.comm.config.js
- 哪些是特有的
- 安裝插件進(jìn)行合并:
npm i webpack-merge -D
- 抽取公共配置:
-
webpack 跑在 node 當(dāng)中,node 支持 commonjs
-
prod
const { merge } = require("webpack-merge");
const commonConfig = require("./webpack.comm.config");
module.exports = merge(commonConfig, {
mode: production,
output: {
clean: true,
},
});
- dev
const { merge } = require('webpack-merge')
const commonConfig = require('./webpack.comm.config')
module.exports = merge(commonConfig,{
mode: development,
devServer: {
hot: true,
// 端口位置
port: 8888,
// host設(shè)置主機(jī)地址,默認(rèn)值是 localhost
host: "0.0.0.0",
open: ture,
// 自動(dòng)把打包的文件進(jìn)行g(shù)zip壓縮
compress: true,
},
})
- vue
- 把所有和 webpack 有關(guān)的放在了 service-cli 里面
四、補(bǔ)充
4.1 命令行
- 回到上一層目錄:cd …
- 清空命令行:cls
- 切換盤(pán)符:f:
4.2 開(kāi)發(fā)
- 分享代碼:刪除node_modules發(fā)給同事
五、Node跨域
5.1 跨域
- 瀏覽器的同源策略:
- 同源策略是一個(gè)重要的安全策略,它用于限制一個(gè) origin 的文檔或者它加載的腳本如何能與另一個(gè)源的資源進(jìn)行交互。它能幫助阻隔惡意文檔,減少可能被攻擊的媒介
- 如果兩個(gè) URL 的 protocol、port (en-US) (如果有指定的話) 和 host 都相同的話,則這兩個(gè) URL 是同源
- 這個(gè)方案也被稱為“協(xié)議/主機(jī)/端口元組”,或者直接是“元組”。
- 跨域的產(chǎn)生和前端分離的發(fā)展有很大的關(guān)系
- 早期的服務(wù)器端渲染的時(shí)候,是沒(méi)有跨域的問(wèn)題的
- 但是隨著前后端的分離,目前前端開(kāi)發(fā)的代碼和服務(wù)器開(kāi)發(fā)的 API 接口往往是分離的,甚至部署在不同的服務(wù)器上的
- 訪問(wèn)靜態(tài)資源服務(wù)器 和 API 接口服務(wù)器 很有可能不是同一個(gè)服務(wù)器或者不是同一個(gè)端口
- 瀏覽器發(fā)現(xiàn)靜態(tài)資源和 API 接口(XHR、Fetch)請(qǐng)求不是來(lái)自同一個(gè)地方時(shí)(同源策略),就產(chǎn)生了跨域
- 靜態(tài)資源服務(wù)器和 API 服務(wù)器(其他資源類同)是同一臺(tái)服務(wù)器時(shí),是沒(méi)有跨域問(wèn)題的
5.2 跨域解決
- 跨域的解決方案幾乎都和服務(wù)器有關(guān)系,單獨(dú)的前端基本解決不了跨域
- webpack 配置的本質(zhì)也是在 webpack-server 的服務(wù)器中配置了代理
- 解決方案
- 方案一:靜態(tài)資源和 API 服務(wù)器部署在同一個(gè)服務(wù)器中
- 方案二:服務(wù)器中開(kāi)啟CORS, 即是指跨域資源共享
- 方案三:node 代理服務(wù)器(webpack中就是它,開(kāi)發(fā)階段使用)
- 方案四:Nginx 反向代理(真正部署的時(shí)候使用)
- 不常用:
- jsonp:現(xiàn)在很少使用了(曾經(jīng)流行過(guò)一段時(shí)間)
- postMessage
- websocket:為了解決跨域,所有的接口都變成 socket 通信
5.3 前端請(qǐng)求代碼
<script>
// 1.XHR網(wǎng)絡(luò)請(qǐng)求
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
console.log(JSON.parse(xhr.responseText))
}
}
xhr.open('get', 'http://localhost:8000/users/list')
xhr.send()
// 2.fetch網(wǎng)絡(luò)請(qǐng)求
fetch('http://localhost:8000/users/list').then(async res => {
const result = await res.json()
console.log(result)
})
</script>
5.4 CORS
- 跨源資源共享(CORS, Cross-Origin Resource Sharing 跨域資源共享)
- 它是一種基于 http header 的機(jī)制
- 該機(jī)制通過(guò)允許服務(wù)器標(biāo)示除了它自己以外的其它源(域、協(xié)議和端口),使得瀏覽器允許這些 origin 訪問(wèn)加載自己的資源。
- 瀏覽器將 CORS 請(qǐng)求分成兩類:簡(jiǎn)單請(qǐng)求和非簡(jiǎn)單請(qǐng)求。
- 只要同時(shí)滿足以下兩大條件,就屬于簡(jiǎn)單請(qǐng)求(不滿足就屬于非簡(jiǎn)單請(qǐng)求)
- 請(qǐng)求方法是以下是三種方法之一
- HEAD
- GET
- POST
- HTTP 的頭信息不超出以下幾種字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三個(gè)值 application/x-www-form-urlencoded、multipart/form-data、text/plain
- 請(qǐng)求方法是以下是三種方法之一
六、模塊化原理 - source-map
6.1 source-map
-
安裝:
npm init -y
npm i webpack webpack-cli -D
-
mode
- 看起來(lái)設(shè)置了一個(gè)屬性,實(shí)際上有更多的一個(gè)配置
-
devtool:“eval”
- 設(shè)置 source-map
-
代碼通常運(yùn)行在瀏覽器上時(shí),是通過(guò) 打包壓縮 的:
- 也就是真實(shí)跑在瀏覽器上的代碼,和編寫(xiě)的代碼其實(shí)是有差異的
- 比如 ES6 的代碼可能被轉(zhuǎn)換成 ES5
- 比如對(duì)應(yīng)的代碼行號(hào)、列號(hào)在經(jīng)過(guò)編譯后肯定會(huì)不一致
- 比如代碼進(jìn)行丑化壓縮時(shí),會(huì)將編碼名稱等修改
- 比如使用了 TypeScript 等方式編寫(xiě)的代碼,最終轉(zhuǎn)換成 JavaScript
-
但是,當(dāng)代碼報(bào)錯(cuò)需要調(diào)試時(shí)(debug),調(diào)試轉(zhuǎn)換后的代碼是很困難的
-
但是能保證代碼不出錯(cuò)嗎?不可能。
-
那么如何可以調(diào)試這種轉(zhuǎn)換后不一致的代碼呢?答案就是 source-map
- source-map 是從已轉(zhuǎn)換的代碼,映射 到原始的源文件
- 使瀏覽器可以重構(gòu)原始源并在調(diào)試器中顯示重建的原始源
6.2 使用 source-map
- 配置:
devtool:'source-map',
- 使用:
- 第一步:根據(jù)源文件,生成 source-map文件,webpack 在打包時(shí),可以通過(guò)配置生成source-map
- 第二步:在轉(zhuǎn)換后的代碼,最后添加一個(gè)注釋,它指向 sourcemap
- //# sourceMappingURL=common.bundle.js.map
- 瀏覽器會(huì)根據(jù)注釋,查找相應(yīng)的 source-map ,并且根據(jù) source-map 還原代碼,方便進(jìn)行調(diào)試
6.3 分析 source-map
- 最初 source-map生成的文件大小是原始文件的10倍,第二版減少了約50%,第三版又減少了50%,所以目前一個(gè)133kb的文件,最終的 source-map 的大小大概在300 kb
-
目前的 source-map 長(zhǎng)什么樣子
- version:當(dāng)前使用的版本,也就是最新的第三版
- sources:從哪些文件轉(zhuǎn)換過(guò)來(lái)的source-map和打包的代碼(最初始的文件)
- names:轉(zhuǎn)換前的變量和屬性名稱(目前使用的是development模式,所以不需要保留轉(zhuǎn)換前的名稱)
- mappings:source-map用來(lái)和源文件映射的信息(比如位置信息等),一串base64 VLQ(veriable-length quantity可變長(zhǎng)度值)編碼
- file:打包后的文件(瀏覽器加載的文件)
- sourceContent:轉(zhuǎn)換前的具體代碼信息(和sources是對(duì)應(yīng)的關(guān)系)
- sourceRoot:所有的sources相對(duì)的根目錄
- 幫助進(jìn)行調(diào)試
6.4 生成 source-map
-
在使用 webpack打包的時(shí)候,生成對(duì)應(yīng)的source-map
- webpack 提供了非常多的選項(xiàng)(目前是26個(gè)),來(lái)處理 source-map
- https://webpack.docschina.org/configuration/devtool/
- 選擇不同的值,生成的 source-map 會(huì)稍微有差異,打包的過(guò)程也會(huì)有性能的差異,可以根據(jù)不同的情況進(jìn)行選擇
-
下面幾個(gè)值不會(huì)生成 source-map
- false:不使用 source-map,也就是沒(méi)有任何和 source-map 相關(guān)的內(nèi)容。
- none:production 模式下的默認(rèn)值(什么值都不寫(xiě)) ,不生成 source-map。
-
eval:development 模式(開(kāi)發(fā)模式)下的默認(rèn)值,不生成 source-map
- 但是它會(huì)在 eval 執(zhí)行的代碼中,添加 //# sourceURL=
- 它會(huì)被瀏覽器在執(zhí)行時(shí)解析,并且在調(diào)試面板中生成對(duì)應(yīng)的一些文件目錄,方便調(diào)試代碼
- 可以還原源代碼,但是記錄的信息沒(méi)有那么準(zhǔn)確
## 6.5 source-map 值
- 一般在 production 文件設(shè)置
-
source-map
- 生成一個(gè)獨(dú)立的 source-map文件,并且在 bundle 文件中有一個(gè)注釋,指向 source-map文件
-
bundle文件中有如下的注釋://# sourceMappingURL=bundle.js.map
- 開(kāi)發(fā)工具會(huì)根據(jù)這個(gè)注釋找到 source-map文件,并且解析
6.6 設(shè)置
- production:默認(rèn)為 none,不需要設(shè)置
- development:默認(rèn)為 eval
- production:source-map
- 上線之后再做調(diào)試需要使用
6.7 eval-source-map 值
- eval-source-map:會(huì)生成 sourcemap,但是 source-map是以 DataUrl 添加到 eval 函數(shù)的后面
6.8 inline-source-map 值
- inline-source-map:會(huì)生成 sourcemap,但是 source-map是以 DataUrl 添加到 bundle 文件的后面
6.9 cheap-source-map
- 會(huì)生成 sourcemap,但是會(huì)更加高效一些(cheap低開(kāi)銷),因?yàn)樗鼪](méi)有生成列映射(Column Mapping)
- 因?yàn)樵陂_(kāi)發(fā)中,只需要行信息通常就可以定位到錯(cuò)誤了
- 需要用到開(kāi)發(fā)環(huán)境中:
mode:development
6.10 cheap-module-source-map
-
會(huì)生成 sourcemap,類似于 cheap-source-map,但是對(duì)源自 loader 的 sourcemap 處理會(huì)更好
-
需要用到開(kāi)發(fā)環(huán)境中:
mode:development
6.11 hidden-source-map
- 需要用到生產(chǎn)環(huán)境中:
mode:production
- 會(huì)生成 sourcemap,但是不會(huì)對(duì) source-map文件進(jìn)行引用,瀏覽器沒(méi)有下載
- 相當(dāng)于刪除了打包文件中對(duì) sourcemap 的引用注釋
- 手動(dòng)添加
// 被刪除掉的
//# sourceMappingURL=bundle.js.map
6.12 nosources-source-map
- 會(huì)生成 sourcemap,但是生成的 sourcemap 只有錯(cuò)誤信息的提示,不會(huì)生成源代碼文件
- 點(diǎn)擊錯(cuò)誤信息,但是點(diǎn)開(kāi)并沒(méi)有
6.13 多個(gè)值的組合
- 事實(shí)上,webpack 提供的26個(gè)值,是可以進(jìn)行多組合的
-
組合的規(guī)則如下:
- inline-|hidden-|eval:三個(gè)值時(shí)三選一
- nosources:可選值
- cheap可選值,并且可以跟隨module的值;
- 那么在開(kāi)發(fā)中,最佳的實(shí)踐
- 開(kāi)發(fā)階段:推薦使用 source-map 或者 cheap-module-source-map
- 這分別是vue和react使用的值,可以獲取調(diào)試信息,方便快速開(kāi)發(fā)
- 測(cè)試階段:推薦使用 source-map 或者 cheap-module-source-map
- 測(cè)試階段也希望在瀏覽器下看到正確的錯(cuò)誤提示
- 發(fā)布階段:false、缺省值(不寫(xiě))
- 開(kāi)發(fā)階段:推薦使用 source-map 或者 cheap-module-source-map
七、深入 Babel - polyfill
7.1 Babel - polyfill
-
webpack 底層就是使用 babel 轉(zhuǎn)換代碼
-
Babel是一個(gè)工具鏈,主要用于舊瀏覽器或者環(huán)境中將 ECMAScript 2015+ 代碼轉(zhuǎn)換為向后兼容版本的 JavaScript
-
包括:語(yǔ)法轉(zhuǎn)換、源代碼轉(zhuǎn)換、Polyfill 實(shí)現(xiàn)目標(biāo)環(huán)境缺少的功能等
7.2 Babel 命令行使用
- babel 本身可以作為一個(gè)獨(dú)立的工具(和 postcss 一樣),不和 webpack 等構(gòu)建工具配置來(lái)單獨(dú)使用
- 在命令行使用 babel,需要安裝如下庫(kù):
npm install @babel/cli @babel/core
- 安裝插件:
npm i @babel/plugin-transform-block-scoping -D
npm i @babel/plugin-transform-arrow-functions -D
- 安裝插件:
- 使用 babel 來(lái)處理源代碼:
npx babel src --out-dir dist
- src:源文件的目錄 ./src
- –out-dir:要輸出的文件夾 dist ./build
7.3 Babel 的預(yù)設(shè) preset
- 如果要轉(zhuǎn)換的內(nèi)容過(guò)多,一個(gè)個(gè)設(shè)置是比較麻煩的,可以使用預(yù)設(shè)(preset)
-
安裝@babel/preset-env預(yù)設(shè):
npm install @babel/preset-env -D
- 執(zhí)行如下命令:
npx babel src --out-dir dist --presets=@babel/preset-env
7.4 Babel 的底層原理
-
babel 將一段代碼(ES6、TypeScript、React)轉(zhuǎn)成另外一段代碼(ES5)
- 從一種源代碼(原生語(yǔ)言)轉(zhuǎn)換成另一種源代碼(目標(biāo)語(yǔ)言)
- 就是編譯器的工作,事實(shí)上可以將 babel 看成就是一個(gè)編譯器
-
Babel 編譯器的作用就是將源代碼轉(zhuǎn)換成瀏覽器可以直接識(shí)別的另外一段源代碼
-
Babel 也擁有編譯器的工作流程
- 解析階段(Parsing)
- 轉(zhuǎn)換階段(Transformation)
- 生成階段(Code Generation)
-
使用:如果沒(méi)有webpack 需要單獨(dú)敲對(duì)應(yīng)的命令:
npx babel
- 結(jié)合 webpack 進(jìn)行使用:
npm i webpack webpack-cli -D
- 結(jié)合 webpack 進(jìn)行使用:
-
webpack 對(duì)應(yīng)的是模塊化的內(nèi)容,babel 對(duì)應(yīng)的是es6 轉(zhuǎn)化為es5的內(nèi)容–兩者結(jié)合在一起
7.5 babel-loader
- 安裝:
npm install babel-loader @babel/core -D
- @babel/core 會(huì)自動(dòng)安裝
- 必須指定使用的插件才會(huì)生效
module: {
rules: [
{
test: /\.js$/,
use: {
loader: "babel-loader", //會(huì)自動(dòng)去找對(duì)應(yīng)的 babel 工具
options: {
// plugins: ["@babel/plugin-transform-arrow-functions", "@babel/plugin-transform-block-scoping"],
presets: ["@babel/preset-env"],
},
},
},
],
},
- webpack 與 對(duì)應(yīng)的另外一個(gè)工具結(jié)合起來(lái)都是使用對(duì)應(yīng)的 loader
7.6 babel-preset
- **可以直接給 webpack 提供一個(gè) preset,**webpack會(huì)根據(jù)預(yù)設(shè)來(lái)加載對(duì)應(yīng)的插件列表,并且將其傳遞給 babel
- 常見(jiàn)的預(yù)設(shè)有三個(gè)
- env:適配的環(huán)境
- react:對(duì) react 代碼進(jìn)行轉(zhuǎn)換
- TypeScript
- 安裝:
npm install @babel/preset-env
7.7 瀏覽器兼容性
-
兼容性:針對(duì)不同的瀏覽器支持的特性:比如 css 特性、js 語(yǔ)法之間的兼容性
-
市面上有大量的瀏覽器:
- 有Chrome、Safari、IE、Edge、Chrome for Android、UC Browser、QQ Browser等等
-
其實(shí)在很多的腳手架配置中,都能看到類似于這樣的配置信息:
-
這里的百分之一,就是指市場(chǎng)占有率
-
> 1% last 2 versions not dead
-
-
代碼要不要自動(dòng)轉(zhuǎn)換取決于要適配的瀏覽器
-
瀏覽器市場(chǎng)占有率caniuse
7.8 browserslist 工具
- 幫助去配置需要兼容的瀏覽器版本
- Browserslist 是一個(gè)在不同的前端工具之間,共享目標(biāo)瀏覽器和 Node.js 版本的配置:
- Autoprefixer:自動(dòng)添加瀏覽器前綴
- Babel
- postcss-preset-env
- eslint-plugin-compat
- stylelint-no-unsupported-browser-features
- postcss-normalize
- obsolete-webpack-plugin
- 條件查詢使用的是 caniuse-lite 的工具,這個(gè)工具的數(shù)據(jù)來(lái)自于 caniuse 的網(wǎng)站上
- 工程化:很多操作不需要自己來(lái)做,甚至不需要自己來(lái)配置,利用一系列的工具去做這件事情
- 編寫(xiě)規(guī)則
-
defaults:Browserslist的默認(rèn)瀏覽器(> 0.5%, last 2 versions, Firefox ESR, not dead)
- not dead:24 個(gè)月之內(nèi)都沒(méi)有官網(wǎng)更新和支持
- 5%:通過(guò)全局使用情況統(tǒng)計(jì)信息選擇的瀏覽器版本。 >=,<和<=工作過(guò)
- 5% in US:使用美國(guó)使用情況統(tǒng)計(jì)信息。它接受兩個(gè)字母的國(guó)家/地區(qū)代碼
- 5% in alt-AS:使用亞洲地區(qū)使用情況統(tǒng)計(jì)信息。有關(guān)所有區(qū)域代碼的列表,請(qǐng)參見(jiàn)caniuse-lite/data/regions
- 5% in my stats:使用自定義用法數(shù)據(jù)
- 5% in browserslist-config-mycompany stats:使用 來(lái)自的自定義使用情況數(shù)據(jù)browserslist-config-mycompany/browserslist-stats.json
- cover 99.5%:提供覆蓋率的最受歡迎的瀏覽器
- cover 99.5% in US:與上述相同,但國(guó)家/地區(qū)代碼由兩個(gè)字母組成
- cover 99.5% in my stats:使用自定義用法數(shù)據(jù)
- dead:24個(gè)月內(nèi)沒(méi)有官方支持或更新的瀏覽器?,F(xiàn)在是IE 10,IE_Mob 11,BlackBerry 10,BlackBerry 7, Samsung 4和OperaMobile 12.1
- last 2 versions:每個(gè)瀏覽器的最后2個(gè)版本
- last 2 Chrome versions:最近2個(gè)版本的Chrome瀏覽器
- ast 2 major versions或last 2 iOS major versions:最近2個(gè)主要版本的所有次要/補(bǔ)丁版本
-
node 10和node 10.4:選擇最新的Node.js10.x.x 或10.4.x版本
- current node:Browserslist現(xiàn)在使用的 Node.js 版本
- maintained node versions:所有Node.js 版本,仍由 Node.js Foundation 維護(hù)
-
iOS 7:直接使用iOS瀏覽器版本7
- Firefox > 20:Firefox的版本高于20 >=,<并且<=也可以使用。它也可以與Node.js一起使用。
- ie 6-8:選擇一個(gè)包含范圍的版本。
- Firefox ESR:最新的[Firefox ESR]版本
- PhantomJS 2.1和PhantomJS 1.9:選擇類似于PhantomJS運(yùn)行時(shí)的Safari版本
- extends browserslist-config-mycompany:從browserslist-config-mycompanynpm包中查詢 。
- supports es6-module:支持特定功能的瀏覽器
- es6-module這是“我可以使用” 頁(yè)面feat的URL上的參數(shù)。有關(guān)所有可用功能的列表,請(qǐng)參見(jiàn) :caniuse-lite/data/features
- **browserslist config:在Browserslist配置中定義的瀏覽器。**在差異服務(wù)中很有用,可用于修改用戶的配置,例如 browserslist config and supports es6-module。
- since 2015或last 2 years:自2015年以來(lái)發(fā)布的所有版本(since 2015-03以及since 2015-03-10)
- unreleased versions或unreleased Chrome versions:Alpha和Beta版本
- not ie <= 8:排除先前查詢選擇的瀏覽器
-
defaults:Browserslist的默認(rèn)瀏覽器(> 0.5%, last 2 versions, Firefox ESR, not dead)
- 命令行使用,自己添加規(guī)則:
npx browserslist ">1%, last 2 version, not dead"
,真實(shí)開(kāi)發(fā)不會(huì)使用
7.9 配置browserslist
- 查看是否安裝:node_modules
- 寫(xiě)法一:在package.json中配置:
"browserslist":[]
- 寫(xiě)法二:?jiǎn)为?dú)的一個(gè)配置文件 .browserslistrc 文件,寫(xiě)上對(duì)應(yīng)的規(guī)則
7.10 設(shè)置目標(biāo)瀏覽器 browserslist/ targets
-
最終打包的 JavaScript 代碼,是需要跑在目標(biāo)瀏覽器上的,那么如何告知 babel 目標(biāo)瀏覽器
- browserslist 工具
- target 屬性(一般不使用)
- 配置的 targets 屬性會(huì)覆蓋 browserslist
- 但是在開(kāi)發(fā)中,更推薦通過(guò) browserslist來(lái)配置,因?yàn)轭愃朴?postcss工具,也會(huì)使用 browserslist,進(jìn)行統(tǒng)一瀏覽器的適配
7.11 Stage-X 的 preset
-
TC39 的組織
- TC39是指技術(shù)委員會(huì)(Technical Committee)第 39 號(hào)
- 它是 ECMA 的一部分,ECMA 是 “ECMAScript” 規(guī)范下的 JavaScript 語(yǔ)言標(biāo)準(zhǔn)化的機(jī)構(gòu)
- ECMAScript 規(guī)范定義了 JavaScript 如何一步一步的進(jìn)化、發(fā)展
-
TC39 遵循的原則是:分階段加入不同的語(yǔ)言特性,新流程涉及四個(gè)不同的 Stage
- **Stage 0:**strawman(稻草人,圖紙),任何尚未提交作為正式提案的討論、想法變更或者補(bǔ)充都被認(rèn)為是第 0 階段的"稻草人"
- **Stage 1:**proposal(提議),提案已經(jīng)被正式化,并期望解決此問(wèn)題,還需要觀察與其他提案的相互影響
- **Stage 2:**draft(草稿),Stage 2 的提案應(yīng)提供規(guī)范初稿、草稿。此時(shí),語(yǔ)言的實(shí)現(xiàn)者開(kāi)始觀察 runtime 的具體實(shí)現(xiàn)是否合理
- **Stage 3:**candidate(候補(bǔ)),Stage 3 提案是建議的候選提案。在這個(gè)高級(jí)階段,規(guī)范的編輯人員和評(píng)審人員必須在最終規(guī)范上簽字。Stage 3 的提案不會(huì)有太大的改變,在對(duì)外發(fā)布之前只是修正一些問(wèn)題
- **Stage 4:**finished(完成),進(jìn)入 Stage 4 的提案將包含在 ECMAScript 的下一個(gè)修訂版中
- Babel的 Stage-X 設(shè)置,但是從babel7開(kāi)始,已經(jīng)不建議使用了,建議使用preset-env 來(lái)設(shè)置
7.12 Babel 的配置文件
- babel 配置越多的話,不利于維護(hù),建議創(chuàng)建一個(gè)配置文件
-
可以將 babel 的配置信息放到一個(gè)獨(dú)立的文件中,babel 提供了兩種配置文件的編寫(xiě):
- babel.config.json(或者.js,.cjs,.mjs)文件;
- 喜歡以 js 結(jié)尾
- .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)目的子包,更加推薦
7.13 polyfill
-
Polyfill
- 翻譯:一種用于衣物、床具等的聚酯填充材料, 使這些物品更加溫暖舒適
- 理解:更像是應(yīng)該填充物(墊片),一個(gè)補(bǔ)丁,可以幫助更好的使用 JavaScript
-
為什么會(huì)用到 polyfill
- 比如使用了一些語(yǔ)法特性(例如:Promise, Generator, Symbol 等以及實(shí)例方法(特殊的 api )例如 Array.prototype.includes 等)
- 但是某些瀏覽器壓根不認(rèn)識(shí)這些特性,必然會(huì)報(bào)錯(cuò)
- 可以使用 polyfill 來(lái)填充或者說(shuō)打一個(gè)補(bǔ)丁,那么就會(huì)包含該特性了
-
使用
-
babel7.4.0 之前,可以使用 @babel/polyfill的包,但是該包現(xiàn)在已經(jīng)不推薦使用了
-
babel7.4.0 之后,可以通過(guò)單獨(dú)引入 core-js 和 regenerator-runtime 來(lái)完成 polyfill 的使用,安裝:
- 開(kāi)發(fā)生產(chǎn)環(huán)境都要使用
npm install core-js regenerator-runtime
-
配置 babel.config.js
- useBuiltIns:設(shè)置以什么樣的方式來(lái)使用 polyfill
- false
- 打包后的文件不使用 polyfill 來(lái)進(jìn)行適配
- 并且這個(gè)時(shí)候是不需要設(shè)置 corejs 屬性的
- **usage **(推薦使用)
- 會(huì)根據(jù)源代碼中出現(xiàn)的語(yǔ)言特性,自動(dòng)檢測(cè)所需要的 polyfill
- 這樣可以確保最終包里的 polyfill 數(shù)量的最小化,打包的包相對(duì)會(huì)小一些
- 可以設(shè)置 corejs 屬性來(lái)確定使用的 corejs 的版本
- entry
- 如果依賴的某一個(gè)庫(kù)/第三方代碼本身使用了某些 polyfill 的特性,但是因?yàn)槭褂玫氖?usage,所以之后用戶瀏覽器可能會(huì)報(bào)錯(cuò)
- 所以,如果擔(dān)心出現(xiàn)這種情況,可以使用 entry
- 并且需要在入口文件(index.js)中添加 `import ‘core-js/stable’; import ‘regenerator-runtime/runtime’
- 這樣做會(huì)根據(jù) browserslist 目標(biāo)導(dǎo)入所有的 polyfill,但是對(duì)應(yīng)的包也會(huì)變大
- false
- corejs:設(shè)置 corejs 的版本,目前使用較多的是 3.x 的版本,可以在 package.json 文件中進(jìn)行查看
- corejs 可以設(shè)置是否對(duì)提議階段的特性進(jìn)行支持
- 設(shè)置 proposals 屬性為 true
module.exports = { // plugins: ["@babel/plugin-transform-arrow-functions", "@babel/plugin-transform-block-scoping"], presets: [ [ "@babel/preset-env", { // 指定使用版本 corejs: 3, useBuiltIns:false }, ], ], };
- useBuiltIns:設(shè)置以什么樣的方式來(lái)使用 polyfill
-
7.14 React 的 jsx 支持
-
編寫(xiě) react 代碼時(shí),react 使用的語(yǔ)法是 jsx,jsx 是可以直接使用 babel 來(lái)轉(zhuǎn)換的
-
安裝 react :
npm i react react-dom
-
安裝 preset :
npm install @babel/preset-react -D
-
掛載到 index.html 上,需要打包 html 文件:
npm i html-webpack-plugin -D
-
const HtmlWebpackPlugin = require("HtmlWebpackPlugin "); plugins: [ new HtmlWebpackPlugin({ template: "./index.html", }), ],
-
module: { rules: [ { test: /\.jsx?$/, //x?:0或者1個(gè) use: { loader: "babel-loader", //會(huì)自動(dòng)去找對(duì)應(yīng)的 babel 工具 options: { // plugins: ["@babel/plugin-transform-arrow-functions", "@babel/plugin-transform-block-scoping"], presets: [["@babel/preset-env", {}], ["@babel/preset-react"]], }, }, }, ], },
7.15 TypeScript 的編譯
-
可以通過(guò) TypeScript 的 compiler 來(lái)轉(zhuǎn)換成 JavaScript:
npm install typescript -D
-
通過(guò)
tsc --init
為 TypeScript 的編譯配置信息編寫(xiě)一個(gè) tsconfig.json 文件 -
手動(dòng)編譯自己的ts代碼:
npx tsc
7.16 使用 ts-loader
- 安裝:
npm install ts-loader -D
- 在安裝 ts-loader 的時(shí)候會(huì)自動(dòng)安裝 TypeScript 的 compiler
- 配置
{
test: /\.ts$/,
use:'ts-loader'
}
- 通過(guò) npm run build 打包
- 來(lái)直接編譯 TypeScript,那么只能將 ts 轉(zhuǎn)換成 js
- 還希望在這個(gè)過(guò)程中添加對(duì)應(yīng)的 polyfill,那么 ts-loader 是無(wú)能為力的
- 需要借助于 babel 來(lái)完成 polyfill 的填充功能
7.17 使用 babel-loader
-
一般處理 ts 代碼不會(huì)使用 ts-loader 進(jìn)行處理,會(huì)選擇 babel-loader 進(jìn)行處理
- ts-loader 需要單獨(dú)安裝 ts-loader
- 編寫(xiě)代碼過(guò)程也可能用到 polyfill,ts-loader 是沒(méi)有 polyfill 的
- 使用預(yù)設(shè):
npm install @babel/preset-typescript -D
- 來(lái)直接編譯TypeScript,也可以將 ts 轉(zhuǎn)換成 js,并且可以實(shí)現(xiàn) polyfill 的功能
- babel-loader 在編譯的過(guò)程中,不會(huì)對(duì)類型錯(cuò)誤進(jìn)行檢測(cè)
7.18 編譯 TypeScript 最佳實(shí)踐
-
使用 Babel 來(lái)完成代碼的轉(zhuǎn)換,打包代碼
-
使用 tsc 來(lái)進(jìn)行類型的檢查文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-820108.html
-
在 scripts 中添加了兩個(gè)腳本,用于類型檢查文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-820108.html
- 執(zhí)行 npm run type-check可以對(duì) ts 代碼的類型進(jìn)行檢測(cè):校驗(yàn)出代碼有沒(méi)有錯(cuò)誤
- 執(zhí)行 npm run type-check-watch可以實(shí)時(shí)的檢測(cè)類型錯(cuò)誤
-
到了這里,關(guān)于前端工程化之 webpack <一>的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!