最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用babel-plugin-import?實現(xiàn)自動按需引入方式

 更新時間:2022年12月01日 10:13:36   作者:swx980  
這篇文章主要介紹了使用babel-plugin-import?實現(xiàn)自動按需引入方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

babel-plugin-import 實現(xiàn)自動按需引入

Vant 支持一次性導(dǎo)入所有組件,引入所有組件會增加代碼包體積,因此不推薦這種做法

babel-plugin-import 是一款 babel 插件,它會在編譯過程中將 import 的寫法自動轉(zhuǎn)換為按需引入的方式。

1、下載

npm i babel-plugin-import -D

2、

(1)在.babelrc 中添加配置

注意:webpack 1 無需設(shè)置 libraryDirectory

{
? "plugins": [
? ? ["import", {
? ? ? "libraryName": "vant",
? ? ? "libraryDirectory": "es",
? ? ? "style": true
? ? }]
? ]
}

(2)對于使用 babel7 的用戶,可以在 babel.config.js 中配置

module.exports = {
? plugins: [
? ? ['import', {
? ? ? libraryName: 'vant',
? ? ? libraryDirectory: 'es',
? ? ? style: true
? ? }, 'vant']
? ]
};

3、接著你可以在代碼中直接引入 Vant 組件,插件會自動將代碼轉(zhuǎn)化為方式二中的按需引入形式

import { Button } from 'vant';

babel-plugin-import 的組件按需加載原理

對比webpack懶加載

webpack 懶加載是將源碼中的 import、require 引入的文件編譯之后再根據(jù)動態(tài)加載語法配置(通常以頁面路由為基本單位)將較大的代碼拆分并構(gòu)建出較小的 chunk 包,運行時執(zhí)行到相應(yīng)業(yè)務(wù)邏輯時才去加載執(zhí)行對應(yīng) chunk 代碼。

webpack 懶加載主要發(fā)生在 JS 拆分出不同的 Chunk 這一過程中。

babel-plugin-import 按需加載是以組件為基本單位產(chǎn)出 js、css、less 文件,借助插件或者部分引入的寫法,使得項目代碼或 babel 編譯后的代碼中只包含使用到的組件的 js、css、less 等。

首先是執(zhí)行時機不同,babel-plugin-import 按需加載是在源碼編寫階段或者 babel 編譯 js 階段,而 webpack 懶加載則是在構(gòu)建生成打包產(chǎn)物階段。

其次是原理不同,babel-plugin-import 按需加載是在源碼階段就去掉了無關(guān)代碼,而 webpack 懶加載則是將經(jīng)過 tree-shaking 優(yōu)化過后的大文件包進(jìn)行拆分在適當(dāng)?shù)倪\行時進(jìn)行按需加載。兩者并不沖突,可以一前一后共同作用。

實現(xiàn)原理

babel-plugin-import 按需加載目的是減少項目構(gòu)建打包產(chǎn)物的大小,提高項目線上首屏渲染速度,減少白屏?xí)r間,減少流量消耗。

若是采用手動引入需要使用到的組件以及其對應(yīng)的樣式文件,那么在 webpack 構(gòu)件時組件庫中其他未被引入的文件不會被打包。

import Button from 'lib/button';
import 'lib/lib/button/style';

若是自動引入:

npm i babel-plugin-import -D
 
module.exports = {
  plugins: [
    ['import', {
      libraryName,
      libraryDirectory: 'es',
      style: true
    }, libraryName]
  ]
};
 
import { Button } from libraryName;

組件其實就是對一堆 js、css 以及 less 等文件的總稱,自動引入的本質(zhì)是將引入組件的寫法通過插件來轉(zhuǎn)換成手動引入組件對應(yīng)的代碼以及樣式文件的寫法。核心原理依然是對源碼的 import 導(dǎo)入寫法進(jìn)行轉(zhuǎn)換——詞法語法分析,AST轉(zhuǎn)換,代碼生成。

該插件主要參數(shù):

 "libraryName": "", // 組件庫名稱,對應(yīng) import 語法中的包名
  "libraryDirectory": "lib", // 編譯之后各個組件單元所在文件夾名稱
  "style": true, // 是否引入組件對應(yīng)樣式文件,也可以傳入 less 來引入 less 文件
  "styleLibraryDirectory": "", // 編譯之后引入的組件樣式文件所在文件夾名稱
  "camel2DashComponentName": false, // 是否將駝峰命名的導(dǎo)入變量轉(zhuǎn)換為對應(yīng)的橫線連接命名的文件名
  "customName": (name, file) => { return `/lib/${name}` }, // 自定義編譯之后引入的組件名
  "customStyleName": (name, file) => { return `/lib/css/${name}` }, // 自定義編譯之后引入樣式文件的名稱

插件中使用到的鉤子函數(shù)有:

const methods = [
  'ImportDeclaration', 				// import 導(dǎo)入聲明
  'CallExpression',				    // 函數(shù)調(diào)用
  'MemberExpression',
  'Property',
  'VariableDeclarator',
  'ArrayExpression',
  'LogicalExpression',
  'ConditionalExpression',
  'IfStatement',
  'ExpressionStatement',
  'ReturnStatement',
  'ExportDefaultDeclaration',
  'BinaryExpression',
  'NewExpression',
  'ClassDeclaration',
  'SwitchStatement',
  'SwitchCase',
];

 Visitor 對象上還配置了 Program 鉤子,該鉤子是在 babel 處理一個獨立文件(或者叫做模塊更合適,node 規(guī)范定義一個文件就是一個模塊)時執(zhí)行,其中若不按此方式具體指定則默認(rèn)為 enter 鉤子。

const Program = {
  // 進(jìn)入鉤子
  enter(path, options) {
  	// 1. 根據(jù)插件接受到的配置參數(shù)初始化插件 Plugin 數(shù)組
    // 2. 遍歷插件 Plugin 數(shù)組,依次執(zhí)行各個插件的初始化方法 ProgramEnter
  },
  // 退出鉤子
  exit() {
  	// ...
  }
}

轉(zhuǎn)換 import 語法需要識別 ES6 模塊規(guī)范的默認(rèn)導(dǎo)入、部分導(dǎo)入以及整體導(dǎo)入等語法,主要邏輯包括鑒別是否是部分導(dǎo)入,只有部分導(dǎo)入才表示導(dǎo)入具體組件,轉(zhuǎn)換導(dǎo)入變量名等。

// 1. 部分導(dǎo)入
import { Button } from '';
console.log(Button);
 
// 2. 默認(rèn)導(dǎo)入
import default from '';
console.log(default.Button);
 
// 3. 全部導(dǎo)入
import * as D from '';
console.log(D.Button);

整體處理邏輯如下:

  • ImportDeclaration 鉤子中將部分導(dǎo)入、默認(rèn)導(dǎo)入和整體導(dǎo)入的語句記錄到插件全局狀態(tài)對象上,同時將節(jié)點的 path 對象記錄至插件全局狀態(tài)對象上;
  • 插件全局狀態(tài)對象上存儲的 path 對象會在 Program 退出時遍歷執(zhí)行 remove 方法,從而移除了所有原始的導(dǎo)入語句;
  • 在 MemberExpression、CallExpression、buildExpressionHandler、buildDeclaratorHandler等鉤子函數(shù)中執(zhí)行 importMethod 函數(shù);
  • importMethod 函數(shù)會根據(jù)插件的配置參數(shù)計算出真實文件導(dǎo)入路徑、是否導(dǎo)入樣式文件、樣式文件名、是否轉(zhuǎn)換默認(rèn)導(dǎo)入等配置,從而使用 @babel/helper-module-imports 提供的 addSideEffect 方法添加對應(yīng)的部分導(dǎo)入語句。
  • 重命名導(dǎo)入模塊的變量描述符 Identifier。

以鉤子函數(shù)為入口,根據(jù)不同的節(jié)點類型取找到不同節(jié)點與變量相關(guān)的屬性;

校驗變量的 name 是否存在于插件全局狀態(tài)的 specfied 中,即變量是否是導(dǎo)入組件指向的變量;

通過 path.scope.hasBinding、path.scope.getBinding 排除掉其他作用域的變量;

借助 importMethod 方法計算轉(zhuǎn)換后模塊對應(yīng)的變量名然后修改節(jié)點對應(yīng)的變量名。

變量描述符 Identifier可能指向的鉤子有:

Property
VariableDeclarator
ArrayExpression
LogicalExpression
ConditionalExpression
IfStatement
ExpressionStatement
ReturnStatement
ExportDefaultDeclaration
BinaryExpression
NewExpression
SwitchStatement
SwitchCase
ClassDeclaration

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論

南开区| 宁南县| 元朗区| 壤塘县| 石柱| 报价| 星座| 张北县| 霍邱县| 晋州市| 特克斯县| 桦南县| 上栗县| 宿松县| 措美县| 仁布县| 施秉县| 紫金县| 托里县| 洱源县| 宣威市| 高州市| 彭泽县| 读书| 当涂县| 周至县| 嘉黎县| 南澳县| 如东县| 南陵县| 游戏| 罗江县| 长丰县| 五峰| 南开区| 武鸣县| 云和县| 天津市| 庐江县| 奈曼旗| 专栏|