gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区

站長(zhǎng)資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

vscode+babel開發(fā)一個(gè)智能移除未使用變量的插件(實(shí)戰(zhàn))

本篇文章分享一個(gè)在vscode中結(jié)合babel開發(fā)一個(gè)智能移除未使用變量插件的方法,希望對(duì)大家有所幫助!

vscode+babel開發(fā)一個(gè)智能移除未使用變量的插件(實(shí)戰(zhàn))

vscode 已經(jīng)成為前端不可缺失的開發(fā)工具之一,之所以 vscode 能夠獲得開發(fā)者的青睞,我想和它“無(wú)所不能”的插件體系有很大一部分關(guān)系。在工作中我們能用它來(lái)開發(fā)純工具型的插件,也可以用它開發(fā)一些和公司業(yè)務(wù)相結(jié)合的功能插件。在這里我分享一個(gè)通過(guò)結(jié)合babel來(lái)實(shí)現(xiàn)一個(gè)能夠智能移除未使用的變量插件,希望對(duì)大家開發(fā) vscode 插件有一定的啟發(fā)和幫助。【推薦學(xué)習(xí):《vscode入門教程》】

正文

今天我們首先來(lái)熟悉一下 vscode 插件項(xiàng)目的搭建流程

1、使用官方提供的腳手架初始化一個(gè)項(xiàng)目

安裝腳手架

# npm 形式 npm install -g yo generator-code # yarn 形式 yarn global add yo generator-code

運(yùn)行腳手架

# 運(yùn)行腳手架 yo code

選擇模板,考慮到有些開發(fā)者對(duì) TypeScript 并不熟悉,所以我們這里選擇 New Extension (JavaScript)

? What type of extension do you want to create? New Extension (JavaScript) ? What's the name of your extension? rm-unuse-var ? What's the identifier of your extension? rm-unuse-var ? What's the description of your extension? 移除未使用的變量 ? Enable JavaScript type checking in 'jsconfig.json'? Yes ? Initialize a git repository? Yes ? Which package manager to use? yarn

這是我們最終生成的目錄結(jié)構(gòu)

vscode+babel開發(fā)一個(gè)智能移除未使用變量的插件(實(shí)戰(zhàn))

我們先來(lái)運(yùn)行一下這個(gè)插件試試

vscode+babel開發(fā)一個(gè)智能移除未使用變量的插件(實(shí)戰(zhàn))

點(diǎn)擊上面運(yùn)行按鈕,會(huì)打開一個(gè)新的 vscode 窗口,在新窗口中按下Ctrl+Shift+P輸入Hello World,在窗口右下角會(huì)看到一個(gè)提示框,說(shuō)明我們第一個(gè) vscode 插件運(yùn)行成功運(yùn)行了。

vscode+babel開發(fā)一個(gè)智能移除未使用變量的插件(實(shí)戰(zhàn))

2、自定義命令、快捷鍵、菜單

vscode 插件很多功能都是基于一個(gè)個(gè)命令實(shí)現(xiàn)的,我們可以自定義一些命令,這個(gè)命令將出現(xiàn)在按下Ctrl+Shift+P后的命令列表里面,同時(shí)可以給命令配置快捷鍵、配置資源管理器菜單、編輯器菜單、標(biāo)題菜單、下拉菜單、右上角圖標(biāo)等。

3、如何添加命令列表

package.json 部分配置

{   // 擴(kuò)展的激活事件   "activationEvents": ["onCommand:rm-unuse-var.helloWorld"],   // 入口文件   "main": "./extension.js",   // 添加指令   "contributes": {     "commands": [       {         // 這里的值必須和activationEvents里面配置的一樣         "command": "rm-unuse-var.helloWorld",         // 這個(gè)就是我們指令的名稱,可以修改這里的值重新運(yùn)行插件試試看         "title": "Hello World"       }     ]   } }

在開發(fā)中快捷鍵的使用方式是最便捷的,接下來(lái)我們修改一下配置,讓插件支持快捷鍵的方式運(yùn)行。

{   "contributes": {     "commands": [       {         // 這里的值必須和activationEvents里面配置的一樣         "command": "rm-unuse-var.helloWorld",         // 這個(gè)就是我們指令的名稱,可以修改這里的值重新運(yùn)行插件試試看         "title": "Hello World"       }     ],     // 快捷鍵綁定     "keybindings": [       {         "command": "rm-unuse-var.helloWorld",         "key": "ctrl+6",         "mac": "cmd+6"       }     ]   } }

我們?cè)僦匦逻\(yùn)行一下,通過(guò)快捷鍵Ctrl+6看看我們的插件是否能夠正常運(yùn)行。沒錯(cuò)就是這么簡(jiǎn)單,我們的插件已經(jīng)能夠支持快捷鍵的形式運(yùn)行了。

4、叫 helloWorld 太土了,下一步我們來(lái)修改一下指令的名稱

package.json

{   "activationEvents": ["onCommand:rm-unuse-var.rm-js-var"],   "main": "./extension.js",   "contributes": {     "commands": [       {         "command": "rm-unuse-var.rm-js-var",         "title": "Hello World"       }     ],     "keybindings": [       {         "command": "rm-unuse-var.rm-js-var",         "key": "ctrl+6",         "mac": "cmd+6"       }     ]   } }

因?yàn)槲覀冊(cè)?code>extension.js中注冊(cè)了指令的名稱,所以也要同步修改

let disposable = vscode.commands.registerCommand(   "rm-unuse-var.rm-js-var",   function () {     vscode.window.showInformationMessage("Hello World from rm-unuse-var!");   } );

5、安裝babel相關(guān)庫(kù)

我們修改代碼可以分為 3 個(gè)步驟

1、將代碼解析成 AST 語(yǔ)法樹 2、遍歷修改 AST 語(yǔ)法樹 3、根據(jù)修改過(guò)的 AST 語(yǔ)法樹生成新的代碼

這 3 個(gè)步驟 babel 都有對(duì)應(yīng)的庫(kù)來(lái)處理

  • @babel/parser生成 AST 語(yǔ)法樹,文檔地址(https://www.babeljs.cn/docs/babel-parser)

  • @babel/traverse遍歷 AST 語(yǔ)法樹,文檔地址(https://www.babeljs.cn/docs/babel-traverse)

  • @babel/generator根據(jù) AST 語(yǔ)法樹生成代碼,文檔地址(https://www.babeljs.cn/docs/babel-generator)

  • @babel/types工具庫(kù),文檔地址(https://www.babeljs.cn/docs/babel-types)

6、我們來(lái)看下這些庫(kù)的基本用法,比如實(shí)現(xiàn)一個(gè)將 es6 的箭頭函數(shù)轉(zhuǎn)換成普通函數(shù)

轉(zhuǎn)換前

const say = () => {   console.log("hello"); };

轉(zhuǎn)換后

function say() {   console.log("hello"); }

代碼實(shí)現(xiàn),代碼部分寫死僅供學(xué)習(xí)參考

const t = require("@babel/types"); const parser = require("@babel/parser"); const traverse = require("@babel/traverse").default; const generate = require("@babel/generator").default; // 1、將代碼解析成 AST 語(yǔ)法樹 const ast = parser.parse(`const say = () => {   console.log("hello"); };`); // 2、遍歷修改 AST 語(yǔ)法樹 traverse(ast, {   VariableDeclaration(path) {     const { node } = path;     // 寫死找到第一個(gè)申明     const declaration = node.declarations[0];     // 定義的內(nèi)容     const init = declaration.init;     // 判斷是否是箭頭函數(shù)     if (t.isArrowFunctionExpression(init)) {       // 將原來(lái)的表達(dá)式替換成新生成的函數(shù)       path.replaceWith(         t.functionDeclaration(           declaration.id,           init.params,           init.body,           init.generator,           init.async         )       );     }   }, }); // 3、根據(jù)修改過(guò)的 AST 語(yǔ)法樹生成新的代碼 console.log(generate(ast).code); /* function say() {   console.log("hello"); } */

很多同學(xué)肯定好奇現(xiàn)在我們的表達(dá)式比較簡(jiǎn)單還好,如果復(fù)雜的話定義嵌套會(huì)非常深和復(fù)雜,這個(gè)時(shí)候應(yīng)該怎么知道去替換哪個(gè)節(jié)點(diǎn)?。其實(shí)這里可以借助astexplorer.net/ 這是一個(gè)在線轉(zhuǎn)換 AST 的網(wǎng)站。我們可以打開兩個(gè)窗口,把轉(zhuǎn)換前的代碼放到第一個(gè)窗口,把需要轉(zhuǎn)換的接口放到第二個(gè)窗口。這個(gè)時(shí)候我們就可以對(duì)比一下轉(zhuǎn)換前后的差異,來(lái)實(shí)現(xiàn)我們的代碼了。

vscode+babel開發(fā)一個(gè)智能移除未使用變量的插件(實(shí)戰(zhàn))

vscode+babel開發(fā)一個(gè)智能移除未使用變量的插件(實(shí)戰(zhàn))

6、思考插件如何實(shí)現(xiàn)?

1、獲取編輯器當(dāng)前打開的 js 文件的代碼 2、將代碼解析成 AST 語(yǔ)法樹 3、遍歷 AST 語(yǔ)法樹,刪除未使用的定義 4、根據(jù)修改過(guò)的 AST 語(yǔ)法樹生成新的代碼 5、替換當(dāng)前 js 文件的代碼

其中 2、4 我們已經(jīng)會(huì)了,接下來(lái)只需要看下 1、3、5 如何實(shí)現(xiàn)就行

1 和 5 我們可以通過(guò) vscode 提供的方法

1、獲取編輯器當(dāng)前打開的 js 文件的代碼

import * as vscode from "vscode"; // 當(dāng)前打開的文件 const { activeTextEditor } = vscode.window; // 然后通過(guò)document下的getText就能輕松獲取到我們的代碼了 const code = activeTextEditor.document.getText();

5、替換當(dāng)前 js 文件的代碼

activeTextEditor.edit((editBuilder) => {   editBuilder.replace(     // 因?yàn)槲覀円募鎿Q,所以我們需要定義一個(gè)從頭到位的區(qū)間     new vscode.Range(       new vscode.Position(0, 0),       new vscode.Position(activeTextEditor.document.lineCount + 1, 0)     ),     // 我們的新代碼     generate(ast).code   ); });

好了接下來(lái)我們就剩核心的第 3 步了。

3、遍歷 AST 語(yǔ)法樹,刪除未使用的定義

我們先來(lái)分析一下,未使用的定義包含了哪些?

import vue from "vue"; const a = { test1: 1, test2: 2 }; const { test1, test2 } = a; function b() {} let c = () => {}; var d = () => {};

然后在線 ast 轉(zhuǎn)換網(wǎng)站,復(fù)制這些內(nèi)容進(jìn)去看看生成的語(yǔ)法樹結(jié)構(gòu)

vscode+babel開發(fā)一個(gè)智能移除未使用變量的插件(實(shí)戰(zhàn))

我們先來(lái)實(shí)現(xiàn)一個(gè)例子吧,比如把下面代碼中沒有用的變量移除掉

轉(zhuǎn)換前

var a = 1; var b = 2; console.log(a);

轉(zhuǎn)換后

var a = 1; console.log(a);
  • scope.getBinding(name) 獲取當(dāng)前所有綁定
  • scope.getBinding(name).referenced 綁定是否被引用
  • scope.getBinding(name).constantViolations 獲取當(dāng)前所有綁定修改
  • scope.getBinding(name).referencePaths 獲取當(dāng)前所有綁定路徑

代碼實(shí)現(xiàn)

const t = require("@babel/types"); const parser = require("@babel/parser"); const traverse = require("@babel/traverse").default; const generate = require("@babel/generator").default;  const ast = parser.parse(`var a = 1; var b = 2; console.log(a);`);  traverse(ast, {   VariableDeclaration(path) {     const { node } = path;     const { declarations } = node;     // 此處便利可以處理 const a = 1,b = 2; 這種場(chǎng)景     node.declarations = declarations.filter((declaration) => {       const { id } = declaration;       // const { b, c } = a;       if (t.isObjectPattern(id)) {         // path.scope.getBinding(name).referenced 判斷變量是否被引用         // 通過(guò)filter移除掉沒有使用的變量         id.properties = id.properties.filter((property) => {           const binding = path.scope.getBinding(property.key.name);           return !!binding?.referenced;         });         // 如果對(duì)象中所有變量都沒有被應(yīng)用,則該對(duì)象整個(gè)移除         return id.properties.length > 0;       } else {         // const a = 1;         const binding = path.scope.getBinding(id.name);         return !!binding?.referenced;       }     });     // 如果整個(gè)定義語(yǔ)句都沒有被引用則整個(gè)移除     if (node.declarations.length === 0) {       path.remove();     }   }, }); console.log(generate(ast).code);

7、了解基本處理流程之后,我們就來(lái)看下最終的代碼實(shí)現(xiàn)吧

const t = require("@babel/types"); const parser = require("@babel/parser"); const traverse = require("@babel/traverse").default; const generate = require("@babel/generator").default;  const ast = parser.parse(   `import vue from 'vue';   var a = 1; var b = 2; var { test1, test2 } = { test1: 1, test2: 2 }; function c(){} function d(){} d(); console.log(a, test1);`,   {     sourceType: "module",   } );  traverse(ast, {   // 處理 const var let   VariableDeclaration(path) {     const { node } = path;     const { declarations } = node;      node.declarations = declarations.filter((declaration) => {       const { id } = declaration;       if (t.isObjectPattern(id)) {         id.properties = id.properties.filter((property) => {           const binding = path.scope.getBinding(property.key.name);           return !!binding?.referenced;         });         return id.properties.length > 0;       } else {         const binding = path.scope.getBinding(id.name);         return !!binding?.referenced;       }     });      if (node.declarations.length === 0) {       path.remove();     }   },   // 處理 import   ImportDeclaration(path) {     const { node } = path;     const { specifiers } = node;     if (!specifiers.length) {       return;     }     node.specifiers = specifiers.filter((specifier) => {       const { local } = specifier;       const binding = path.scope.getBinding(local.name);       return !!binding?.referenced;     });     if (node.specifiers.length === 0) {       path.remove();     }   },   // 處理 function   FunctionDeclaration(path) {     const { node } = path;     const { id } = node;     const binding = path.scope.getBinding(id.name);     if (!binding?.referenced) {       path.remove();     }   }, }); console.log(generate(ast).code);

8、vscode 設(shè)置我們的插件只支持 js 文件的限制

因?yàn)槲覀儸F(xiàn)在實(shí)現(xiàn)是針對(duì) js 文件的,所以打開其他類型的文件我們可以讓我們的快捷鍵失效。 我們可以修改package.jsonpackage.json

{   "contributes": {     "commands": [       {         "command": "rm-unuse-var.remove",         "title": "Hello World"       }     ],     "keybindings": [       {         "command": "rm-unuse-var.remove",         "key": "ctrl+6",         "mac": "cmd+6",         "when": "resourceLangId == javascript"       }     ]   } }

9、整合到我們前面創(chuàng)建的項(xiàng)目中去

此處省略… 相信看了上面這些介紹大家已經(jīng)完全有能力自己整合了

10、打包發(fā)布插件

打包我們可以vsce工具

全局安裝 vsce

# npm npm i vsce -g # yarn yarn global add vsce

打包插件

打包前先修改 README.md 文件否則會(huì)報(bào)錯(cuò)

vsce package

執(zhí)行完畢之后會(huì)生成一個(gè).vsix 文件

如果要在本地 vscode 使用可以直接導(dǎo)入

vscode+babel開發(fā)一個(gè)智能移除未使用變量的插件(實(shí)戰(zhàn))

如果要發(fā)布到市場(chǎng)的話,我們需要先注冊(cè)賬號(hào) https://code.visualstudio.com/api/working-with-extensions/publishing-extension#publishing-extensions

# 登錄賬號(hào) vsce login your-publisher-name # 發(fā)布 vsce publish

發(fā)布成功之后就能在我們的市場(chǎng)上看到了 marketplace.visualstudio.com/items?itemN… 也可以在 vscode 中搜索打我們的插件

vscode+babel開發(fā)一個(gè)智能移除未使用變量的插件(實(shí)戰(zhàn))

總結(jié)

到此為止,相信大家對(duì) vscode 插件開發(fā)的基本流程已經(jīng)有了了解。

覺得文章對(duì)你有所幫助,可以點(diǎn)個(gè)贊

當(dāng)然 vscode 插件還有非常多的配置沒有介紹,后面如果有時(shí)間可以單獨(dú)整理成一篇文章來(lái)介紹

如果在開發(fā)過(guò)程中有問題或者其他前端技術(shù)問題也可以加我微信rjjs1221交流,或者直接在評(píng)論區(qū)回復(fù)。

源碼地址 https://github.com/taoxhsmile/rm-unuse-var

贊(0)
分享到: 更多 (0)
?
網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区
国产野外作爱视频播放| 肉大捧一出免费观看网站在线播放| 中文字幕无码不卡免费视频| 91丝袜超薄交口足| 中文字幕在线视频一区二区三区| 欧美v在线观看| 麻豆av免费在线| 日本不卡一区在线| 亚洲免费在线播放视频| 日本激情视频在线播放| 99久re热视频精品98| 日本中文字幕观看| 97在线免费视频观看| 中国一级大黄大黄大色毛片| 国产不卡的av| 日本免费不卡一区二区| 免费一级特黄录像| 别急慢慢来1978如如2| 国产3p在线播放| 久久久久久综合网| 免费国产成人看片在线| 女人另类性混交zo| 最新天堂中文在线| 妞干网这里只有精品| av网站大全免费| 午夜啪啪小视频| 4444在线观看| 欧美日韩在线成人| 色哺乳xxxxhd奶水米仓惠香| 日本手机在线视频| 色香蕉在线观看| 亚洲77777| 最新av网址在线观看| 欧日韩免费视频| 色一情一区二区三区| 欧美成人精品免费| 911福利视频| 国产精品一线二线三线| 一级黄色录像在线观看| 日韩欧美猛交xxxxx无码| 国产福利一区视频| 日本美女爱爱视频| 在线免费视频一区| 妞干网视频在线观看| www.se五月| 欧美精品第三页| 福利在线一区二区| 亚洲免费成人在线视频| 日本www在线播放| 日日橹狠狠爱欧美超碰| 色男人天堂av| 黄色永久免费网站| 北条麻妃在线观看| 日韩国产小视频| 午夜免费福利网站| 欧美一级裸体视频| 噜噜噜久久亚洲精品国产品麻豆| 奇米777在线| 92看片淫黄大片一级| 国产成人艳妇aa视频在线| 在线观看日本www| 中国黄色片免费看| 欧美成人黑人猛交| japanese在线播放| 国产精品av免费| 中文字幕在线视频一区二区| 亚洲精品久久久久久宅男| 亚洲国产精品三区| 一级黄色香蕉视频| 国产一级特黄a大片免费| 日韩手机在线观看视频| 国语对白做受xxxxx在线中国| 成人在线免费观看网址| 中文字幕在线综合| 两性午夜免费视频| 国产福利精品一区二区三区| 波多野结衣国产精品| 日韩精品在线播放视频| 欧美日韩一区二区三区电影| 国产在线拍揄自揄拍无码| 超碰97在线看| www.av91| 欧美伦理视频在线观看| mm131亚洲精品| 天天综合中文字幕| 欧美日韩中文字幕在线播放 | 大胆欧美熟妇xx| 成人免费在线视频播放| 国产深夜男女无套内射| 久章草在线视频| www.色就是色.com| a级网站在线观看| 夜夜添无码一区二区三区| 韩国日本在线视频| 五月天av在线播放| 欧美激情亚洲天堂| 日韩av资源在线| 黄频视频在线观看| 高清在线观看免费| 超碰中文字幕在线观看| 女人帮男人橹视频播放| 天天操,天天操| 亚洲av毛片在线观看| 大j8黑人w巨大888a片| 57pao国产成永久免费视频| 51xx午夜影福利| 三级在线免费看| 成人在线视频一区二区三区| 色乱码一区二区三区在线| 国内少妇毛片视频| 亚洲一区二区在线视频观看| 免费超爽大片黄| 自拍一级黄色片| 美女网站免费观看视频| 成人午夜免费在线| 亚洲第一天堂久久| 中文字幕无码精品亚洲35| 91丝袜超薄交口足| 色播五月综合网| 日本黄色三级大片| 阿v天堂2017| av在线免费观看国产| 欧美日韩中文在线视频| 国产激情片在线观看| 日韩欧美精品免费| 色中文字幕在线观看| 中文字幕在线视频精品| 女同激情久久av久久| jizz欧美激情18| 亚洲国产精品久久久久爰色欲| 特级黄色片视频| 成人日韩在线视频| 中文字幕在线综合| 涩涩网站在线看| 亚洲精品久久久中文字幕| 欧美伦理片在线看| 五月婷婷六月丁香激情| 国产又猛又黄的视频| 波多野结衣作品集| 99久久国产宗和精品1上映| 日本一区二区黄色| 国产xxxxx在线观看| 色诱视频在线观看| 九九九在线观看视频| 别急慢慢来1978如如2| 波多野结衣xxxx| 欧美性猛交xxxx乱大交91| 国产日韩视频在线播放| 福利在线小视频| 国产 日韩 亚洲 欧美| 99久久国产综合精品五月天喷水| 日本xxxxxxxxxx75| 欧洲熟妇精品视频| www.亚洲高清| 中文字幕免费高| 欧美色图另类小说| 中文字幕 91| 国产欧美久久久久| 欧美一级黄色片视频| 欧美成人乱码一二三四区免费| 日韩av.com| 97国产在线播放| 中文字幕在线观看日| 99久久久精品视频| 国产精品视频黄色| av在线com| 色戒在线免费观看| 日本xxxxxxxxxx75| 天天综合天天添夜夜添狠狠添| 九九热只有这里有精品| 国产又大又黄又粗又爽| 一二三在线视频| 一道本视频在线观看| 2022中文字幕| 久久久久xxxx| 成年人在线看片| 亚洲色成人www永久在线观看| 日本 片 成人 在线| 777久久久精品一区二区三区 | www.久久久精品| 日本www在线视频| 黄色一级视频播放| 日本va中文字幕| 国产深夜男女无套内射| 日本福利视频网站| 亚洲精品国产一区二区三区| 日韩中文字幕免费在线| 国产深夜男女无套内射| 麻豆传媒网站在线观看| 欧美成人福利在线观看| 一卡二卡三卡视频| 50度灰在线观看| 久久久久久久久影视| 99999精品| 欧美日韩大尺度| 欧美日韩在线观看不卡| 国产主播在线看| 日本精品www| 欧在线一二三四区| 欧美国产亚洲一区|