国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

前端工程化實戰-開發企業級CLI

開發 前端
如果我們自己開發一套腳手架,定制自己的模板,復制粘貼的人工流程就會轉換為 cli 的自動化流程, 還可以通過維護不同的模板以適應不同業務需求。既然要開發一套腳手架,站在巨人肩膀上顯然省事多了,我們先來看看業界知名腳手架Vue CLI是如何實現的
1、前言

腳手架大家一定都不陌生,比如我們經常使用的 vue-cli、create-react-app,它可以幫助我們快速的初始化一個項目,無需從零配置,極大的方便我們的開發。到這里你可能會疑惑,既然市面上有成熟的腳手架,為什么需要寫一個屬于自己的腳手架呢。因為公共腳手架雖然強大,但并不能滿足我們的實際開發需求。

例如項目中已有的沉淀,項目架構、接口請求的統一處理、換膚、業務組件、eslint配置等,這些想要用到新項目中,只能通過復制粘貼,會存在以下弊端:

重復性勞動,繁瑣且浪費時間

已有項目沉淀分散在各處,很容易有所遺漏

項目間的配置差異很可能會被忽略

人工操作永遠都有可能犯錯,建新項目時,總要花時間去排錯

如果我們自己開發一套腳手架,定制自己的模板,復制粘貼的人工流程就會轉換為 cli 的自動化流程, 還可以通過維護不同的模板以適應不同業務需求。既然要開發一套腳手架,站在巨人肩膀上顯然省事多了,我們先來看看業界知名腳手架Vue CLI是如何實現的。

 2.Vue CLI 原理分析 

Vue CLI 是一個基于 Vue.js 進行快速開發的完整系統,提供:

通過 @vue/cli 實現的交互式的項目腳手架。

通過 @vue/cli + @vue/cli-service-global 實現的零配置原型開發。

一個運行時依賴 (@vue/cli-service),該依賴:

可升級;

基于 webpack 構建,并帶有合理的默認配置;

可以通過項目內的配置文件進行配置;

可以通過插件進行擴展。

一個豐富的官方插件集合,集成了前端生態中最好的工具。

一套完全圖形化的創建和管理 Vue.js 項目的用戶界面。

2.1全局 vue 執行命令存放在哪里

以mac為例,使用命令 where vue,就可以查到 vue 命令所在位置,找到所在位置后,查看目錄即可分析源碼。

2.2vue命令是從哪里注冊的

找到源碼目錄中的package.json,我們會看到如下代碼:

圖片

可以看到bin字段指定了可執行文件的命令名以及可執行文件的路徑,npm安裝一個依賴時,如果該依賴的package.json中指定了bin的信息,那么同時會創建一個全局的軟連接指向該命令所對應的可執行文件。詳細可查看npm的官方文檔:package.json中bin的使用說明。

2.3依賴包分析

包名

用途

commander

完整的 node.js 命令行解決方案, Commander 負責將參數解析為選項和命令參數

shelljs

用來執行shell命令

inquirer

通用交互式命令行用戶界面的集合

semver

語義化版本控制

chalk

設置終端字符串樣式

2.4腳手架都做了哪些事情

2.4.1 HTML 和靜態資源

html文件是一個會被 html-webpack-plugin 處理的模板。在構建過程中,資源鏈接會被自動注入。另外,Vue CLI 也會自動注入 resource hint (preload/prefetch、manifest 和圖標鏈接 (當用到 PWA 插件時) 以及構建過程中處理的 JavaScript 和 CSS 文件的資源鏈接。

2.4.2  CSS 相關

Vue CLI生成項目支持 PostCSS、CSS Modules 和包含 Sass、Less、Stylus 在內的預處理器,你可以在創建項目的時候選擇預處理器。

2.4.3  webpack 相關

Vue CLI基于 webpack 構建,并帶有合理的默認配置,可以通過項目內的配置文件進行配置,還可以通過插件進行擴展。

2.4.4  模式與環境變量

模式是 Vue CLI 項目中一個重要的概念。默認情況下,一個 Vue CLI 項目有三個模式:

development 模式用于 vue-cli-service servetest 模式用于 vue-cli-service test:unitproduction 模式用于 vue-cli-service build 和 vue-cli-service test:e2e你可以通過傳遞 --mode 選項參數為命令行覆寫默認的模式。

 2.4.5  構建目標

當你運行 vue-cli-service build 時,你可以通過 --target 選項指定不同的構建目標。它允許你將相同的源代碼根據不同的用例生成不同的構建。

通過以上對Vue CLI 的分析,我們就對腳手架工具提供的構建集成能力有了一個大概的了解。這有助于我們在使用具體工具時快速定位問題的邊界,當我們自己設計腳手架的時候,我們也可以參照和借鑒,可以適用于我們業務的有:

  • 通過命令行與用戶交互
  • 根據用戶的選擇生成對應的文件,實現的零配置原型開發

需要做出修改的部分有:

  • 基于 vite 構建,并帶有合理的默認配置;
  • 預定義業務模板,根據用戶選擇生成
  • 業務模板基礎支持:

HTML 和靜態資源處理

內置css預處理器

內置vite配置,可以直接修改vite配置文件

內置test、pre、pro三種模式,并生成對應的配置文件

按照上述總結,讓我們一步一步編寫自己的腳手架吧,首先是通過命令行與用戶交互,那么我們需要有一個可執行命令的名字,也是腳手架的名字,這里我們就叫做dt-fe-cli

3.腳手架實現 

3.1命令行工具編寫

3.1.1  初始化項目

我們的腳手架叫做dt-fe-cli,創建dt-fe-cli文件夾,執行npm init -y初始化倉庫,生成package.json文件。

在dt-fe-cli文件夾下創建bin文件夾,并在里面創建cli.mjs文件,此文件作為我們腳手架的入口,需要將其配置到package.json的bin字段。

{
"name": "@auto/dt-fe-cli",
"version": "0.0.1",
"bin": {
"dt-fe-cli": "bin/cli.mjs"
}
}

這樣我們腳手架的入口就有了,繼續編寫腳手架的功能吧

 3.1.2  指令

dt-fe-cli 作為全局命令,同時提供了很多指令。

dt-fe-cli --version可以查看 dt-fe-cli 版本

dt-fe-cli --help可以查看幫助文檔

dt-fe-cli create xxx可以創建一個項目 ...

圖片

  3.1.3  create命令

create接受一個項目名作為參數,這里還提供了額外選項-f, --force,此選項代表如果本地已經存在同名文件夾,是否覆寫。命令行解決方案需要依賴第三方庫commander

import create from '../lib/create.mjs'

program
.command('create <app-name>')
.description('create a new project powered by dt-fe-cli')
.option("-f, --force", "overwrite target directory if it exists")
.action((projectName, options) => {
create(projectName, options)
})

  3.1.4  create方法設計與實現

執行create命令后,如何創建項目呢,我們公司的項目都是托管在內部gitlab上面的,所以直接使用git clone去拉取模板項目,這里需要依賴第三方庫shelljs,那么這里就需要首先判斷git是否存在,不存在提示并退出。之前我們還寫了一個額外選項,用來表示如果本地已經存在同名文件夾,是否覆寫。若沒有此選項,還需要交互式的詢問,這里需要依賴第三方庫inquirer。

create.mjs:

import chalk from 'chalk'
import fse from 'fs-extra'
import shelljs from 'shelljs'
import path from 'path'
import inquirer from 'inquirer'

async function create(projectName, options) {
const targetDirectory = path.join(process.cwd(), projectName)
try {
// 判斷是否存在git,不存在則提示并退出
if (!shelljs.which('git')) {
console(chalk.red('Sorry, dt-fe-cli requires git'));
return
}
const isExist = await fse.pathExists(targetDirectory)
// 判斷目錄下是否存在同名文件夾
if (isExist) {
if (options.force) {
await fse.remove(targetDirectory);
} else {
const { isOverwrite } = await new inquirer.prompt([
{
name: "isOverwrite", // 與返回值對應
type: "list",
message: "Target directory already exists. Pick an action:",
choices: [
{ name: "Overwrite", value: true },
{ name: "Cancel", value: false },
],
},
]);
// 移除同名文件夾
if (isOverwrite) {
console.log('remove existing directory...')
await fse.remove(targetDirectory);
} else {
return;
}
}
}
// 項目類型
const { projectType } = await new inquirer.prompt([
{
name: "projectType", // 與返回值對應
type: "list",
message: "Please select project type:",
choices: [
{ name: "pc", value: 'pc' },
{ name: "h5", value: 'h5' },
],
},
]);
const PROJECT_MAP = {
pc: 'pc.git',
h5: 'h5.git'
}
// 安裝依賴項目
shelljs.exec(`git clone ${PROJECT_MAP[projectType]} ${projectName}`, async (code, stdout, stderr) => {
if (code === 0) {
progress.start()
try {
// 刪除原有.git
await fse.remove(path.join(process.cwd(), projectName, '.git'))
} catch (error) {
console.log(error)
}
progress.succeed()
console.log(`\r\nSuccessfully created project ${chalk.cyan(projectName)}`);
console.log(`\r\n cd ${chalk.cyan(projectName)}`);
console.log(" git init");
console.log(" pnpm install");
console.log(" pnpm dev");
}
})
} catch (error) {
console.log(error);
}
}

  3.1.5  node版本檢查

執行 create 命令后,創建項目會去 gitlab 拉取代碼下載我們自定義的模版,目前我使用的模版均由 Vite3 創建,Vite3 需要 Node.js 版本 14.18+,16+。所以在使用腳手架時,可以先檢查一下當前 Node.js 版本是否符合,不符合則拋出異常。當前依賴的 Node.js 版本需要將其配置到package.json的engines字段,判斷當前 Node.js 版本是否符合需要依賴第三方庫semver

package.json:

{
"engines": {
"node": ">= 14.18.0"
},
}

cli.mjs:

import { readFile } from 'fs/promises'
import semverSatisfies from 'semver/functions/satisfies.js'

const { engines: { node: requiredVersion }, version } = JSON.parse(
await readFile(
new URL('../package.json', import.meta.url)
)
)

function checkNodeVersion (wanted, id) {
if (!semverSatisfies(process.version, wanted, { includePrerelease: true })) {
console.log(chalk.red(
'You are using Node ' + process.version + ', but this version of ' + id +
' requires Node ' + wanted + '.\nPlease upgrade your Node version.'
))
process.exit(1)
}
}

checkNodeVersion(requiredVersion, 'dt-fe-cli')

到這里,腳手架的基本功能就已經開發完畢了,剩下的就是我們的項目模板了

 3.2模版設計支持功能

圖片

3.2.1  TypeScript

使用 Vite3 構建,Vite3 天然支持引入 .ts 文件

  3.2.2  打包自動上傳CDN

const { execSync } = require('child_process');
const { loadEnv } = require('vite')

const env = process.argv[2]
const { VITE_BASE_URL } = loadEnv(env, process.cwd(), '')
const prefix = `${env}${VITE_BASE_URL}`

execSync(`vite build --mode ${env} --base=https://cdn.com/${prefix}`);
uploadCDN({
Dir: `dist/assets`,
Prefix: prefix
})

  3.2.3  commit 校驗

npm install husky --save-dev
npm pkg set scripts.prepare="husky install"
npm run prepare
npx husky add .husky/pre-commit "npm run lint"
git add .husky/pre-commit

  3.2.4  eslint校驗

ESLint通用配置的部分這里就不再贅述了,這里介紹一下我們業務里面自定義的ESLint插件。eslint校驗大家都很熟悉,市面上也有很多eslint插件,但隨著項目不斷迭代發展,我們團隊的編碼規范使用現有的eslint插件已經無法滿足了,需要自己創建插件,并融入到cli的模板當中。

 創建插件

開始創建插件的最簡單方法是使用 Yeoman 生成器。生成器將指導您設置插件的骨架

npm i -g yo generator-eslint
yo eslint:plugin

以上命令會生成如下目錄

.
├── README.md
├── lib
│ ├── index.js
│ └── rules
├── package.json
└── tests
└── lib
└── rules

插件可以在 ESLint 中使用的額外規則。為此,插件必須導出一個包含規則 ID 到規則的鍵值映射的規則對象,舉個簡單的例子,我們想創建一條不允許使用console.log的規則

  創建規則

yo eslint:rule

此命令會在lib/rules文件夾下創建一個新的js文件,一個規則對應一個可導出的 node 模塊

"use strict";

//-------------------------------------------------------
// Rule Definition
//-------------------------------------------------------

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow unnecessary semicolons",
recommended: true,
url: "https://eslint.org/docs/rules/no-extra-semi"
},
fixable: "code",
schema: [] // no options
},
create(context) {
return {
// callback functions
};
}
};

上面這段代碼是一個規則的源碼文件的基本格式,一個規則的源文件輸出一個對象,它由 meta 和 create 兩部分組成。

  • meta(對象)包含規則的元數據,如規則類型、文檔、可接受參數的schema等等
  • create (function) 返回一個對象,其中包含了 ESLint 在遍歷 JavaScript 代碼的抽象語法樹 AST (ESTree 定義的 AST) 時,用來訪問節點的方法。

核心其實在于create方法,我們若想知道如何編寫create方法,首先要明白其原理,那就是 ESLint 是如何分析我們所編寫的代碼呢?相信大家對此也都有所了解,沒錯,就是AST (Abstract Syntax Tree(抽象語法樹))

  插件原理

圖片

ESLint 解析器將代碼轉換為 ESLint 可以評估的抽象語法樹。默認情況下,ESLint 使用內置的 Espree 解析器,它與標準的 JavaScript 運行時和版本兼容,然后去攔截檢測是否符合我們規定的書寫方式,最后讓其展示報錯、警告或正常通過。ESLint 的核心就是規則(rules),而定義規則的核心就是利用 AST 來做校驗,那就讓我們看一下代碼 AST 中會表現為什么樣子。

圖片

上圖可以看出,console.log對應 AST 中type為ExpressionStatement(表達式語句),表達式類型為CallExpression(調用表達式),被調用者類型為MemberExpression(成員表達式),被調用對象名為console,屬性名為log,根據上述信息,我們就可以來完善create方法了

  編寫規則

"use strict";

//-------------------------------------------------------
// Rule Definition
//-------------------------------------------------------

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
fixable: "code",
schema: [], // no options
},
create(context) {
return {
// key 是 selector
'CallExpression MemberExpression': (node) => {
const { property, object } = node;
// 如果在 AST 中匹配到了console.log,就用 context.report() 來發布警告或錯誤
if (object.name === 'console' && property.name === 'log') {
context.report({
node,
message: 'console.log is forbidden.'
});
}
}
};
}
};

至此,包含一條規則(禁止使用console.log)的 ESLint 插件就編寫完成了,接下來將此項目發布到npm平臺就可以在項目模板中下載使用了

 最后 

本文介紹了如何從零編寫一個我們自己的腳手架,并且可以根據不同業務場景區分模版,把業務已有的積累沉淀進去,以上便是本次分享的全部內容,希望對你有所幫助 ^_^

作者簡介

圖片

 馬春鍵 

主機廠事業部,技術部

2021年加入汽車之家,目前任職于主機廠事業部-技術部-數科技術及系統團隊-前端開發組,主要負責數科前端業務,前端前沿技術探索等工作

責任編輯:武曉燕 來源: 之家技術
相關推薦

2023-09-15 10:33:45

前端工程化commit

2022-12-01 07:46:01

工程化工具

2021-05-18 19:18:50

前端工程化工程

2010-08-04 15:20:15

Flex企業級開發

2015-10-26 10:32:01

前端優化工程化

2022-07-26 17:19:11

前端前端工程化

2022-10-09 14:50:24

前端pnpm工具

2022-08-17 11:33:35

前端配置

2021-06-05 18:01:05

工具Rollup前端

2011-12-06 14:02:27

企業級移動開發

2018-06-15 10:12:04

滴滴前端分支管理

2022-07-06 11:20:16

前端開發

2021-11-25 11:08:07

智能

2023-11-30 12:13:29

開發分離工具

2016-11-01 15:26:27

Dell Foglig企業級Hyper-V

2012-05-15 15:21:29

企業級

2009-12-14 20:13:57

IBM

2022-03-02 21:53:57

Spring數據庫持久化Jar包

2012-09-17 09:50:24

桌面虛擬化

2013-07-23 09:37:04

桌面虛擬化企業級
點贊
收藏

51CTO技術棧公眾號

亚洲综合一区在线| 999精品视频一区二区三区| 在线看片线路1| 国产盗摄精品一区二区三区在线| 91精品国产99久久久久久红楼| 午夜视频一区二区在线观看| 亚洲成人精品视频| 成人午夜在线影视| 色综合激情五月| 麻豆福利视频| 日韩一区在线播放| 91插插插插插插插插| 91在线你懂得| 国产亚洲精品网站| 久久亚洲精华国产精华液| 正在播放一区| 日本欧美一区二区三区乱码| 久久国产精品免费一区| 99精品热6080yy久久| 国产一区二区不卡视频在线观看 | 婷婷五月色综合| 亚洲精品人人| 久久久久欧美| 国产精品日韩精品欧美精品| 精品无码久久久久国产| 国产精品日韩| 深夜福利成人| 国产99一区视频免费 | 日本成人超碰在线观看| 日本一区二区三区精品视频| 日韩av一级电影| 一区二区三区欧美成人| 久久66热偷产精品| 欧美深夜福利视频| 国产女人18水真多18精品一级做| 好男人www社区| 亚洲一区在线观看视频| 极品美乳网红视频免费在线观看| 欧美精品在线观看播放| 爱看av在线入口| 色噜噜狠狠狠综合曰曰曰88av| 国产美女久久| 欧美一区二三区| 国产精品红桃| 2022中文字幕| 亚洲人精品午夜| 黄视频在线播放| 精品亚洲aⅴ在线观看| 国产精品毛片无码| 91精品国产综合久久香蕉922| 99在线精品免费视频九九视| 男女激情免费视频| 亚洲精品国产精华液| 成年人网站在线| 美日韩精品免费视频| 国产精品精品| 中文字幕日韩一区二区三区不卡 | 免费观看成人在线| 成人免费视频网站在线观看| 成人午夜激情| 91精品国产麻豆| 久久中文字幕一区二区| 波多野结衣精品久久| 成人毛片视频在线观看| 在线午夜视频| 日韩成人小视频| 啄木系列成人av电影| 精品伦理一区二区三区| 26uuu亚洲综合色欧美| 国产综合在线观看| 精品国产欧美一区二区三区成人| 亚洲成人日韩| 男人天堂1024| 91麻豆精品国产91久久久久| 噜噜噜狠狠夜夜躁精品仙踪林| 久久久综合香蕉尹人综合网| 国产精品三级电影| av在线网页| 91精品国产综合久久久久久蜜臀| 国产精品主播直播| 国产小视频免费在线观看| 日韩日本欧美亚洲| 国产亚洲高清视频| bdsm在线观看播放视频| 亚洲激情在线观看| 久久国产精品亚洲人一区二区三区| 精品国产无码在线| 色综合久久综合网欧美综合网| 久久国际精品| 日韩欧美三级电影| 精品日本高清在线播放| 精品久久亚洲| 亚洲资源视频| 日韩欧美aaa| av成人综合| 一区二区在线观| 欧美影院一区二区| 亚洲第一二三区| 国产91对白刺激露脸在线观看| 宅男在线国产精品| 91麻豆精品国产91久久久平台 | 美女被人操视频在线观看| 中文字幕av一区二区三区谷原希美| 日韩精品中文字幕第1页| 又粗又黑又大的吊av| 日韩精品一区二区三区蜜臀 | 黄色的视频在线免费观看| 日韩中文字幕网址| 美腿丝袜一区二区三区| 国产youjizz在线| 国产精品久久久av| 中日韩av电影| 国产视频一区二| av影院在线播放| 欧美一区二区三区在| 中文字幕一区二区三区欧美日韩 | 国产精品久久久久aaaa| 成人精品在线| 国产 日韩 亚洲 欧美| 日韩国产精品亚洲а∨天堂免| 亚洲免费中文| 日本中文字幕电影在线免费观看 | 91成人午夜| 99爱视频在线| 最近2019中文字幕在线高清| 日本va欧美va精品| 性欧美videos高清hd4k| 国产综合第一页| 欧美日韩一区二区三区四区| 你懂的国产精品| 成人在线免费观看| 精品一区久久久久久| 在线观看精品一区| 伊人精品成人久久综合软件| 国产高清一区在线观看| 91超碰在线免费观看| 在线视频中文字幕一区二区| 国产精品大片| 天使と恶魔の榨精在线播放| 亚洲免费精品视频| 亚洲欧美色图片| 成人福利视频在线看| 99精品在线免费观看| 一区二区在线播放视频| 国产做受69高潮| 亚洲欧美一区二区三区久本道91| 欧美日中文字幕| 美女网站在线观看| 97久久精品午夜一区二区| 欧美日韩午夜在线| 日日噜噜夜夜狠狠视频欧美人 | 精品久久中文字幕久久av| 亚洲激情中文在线| 高清全集视频免费在线| 小说区视频区图片区| 日韩亚洲综合在线| 成人免费一区二区三区视频 | 99综合电影在线视频| 日韩中文字幕| 久久.com| 国产一区高清视频| 精品久久人人做人人爽| 国产成人免费视频网站高清观看视频| 国产高清精品二区| 精东传媒在线观看| 日韩欧美在线一区二区| 一区二区三区视频免费在线观看| 国产午夜精品久久久久久久| 日本女优一区| 久久av色综合| 黄色国产小视频| 成人自拍偷拍| 在线性视频日韩欧美| 一区二区在线观看av| 国产精品五区| 日韩免费高清视频网站| 大胆av不用播放器在线播放 | 久久国产视频网| 91免费精品国偷自产在线在线| 一区二区三区视频国产日韩 | 中文字幕av一区二区| 亚洲专区一二三| 日韩精品电影在线| 成人av激情人伦小说| 国产黄色片在线观看| 黄色片网址在线观看| 亚洲r级在线观看| 一本色道久久综合狠狠躁篇怎么玩| 亚洲人成7777| 免费成人你懂的| 精品久久一区| 性欧美又大又长又硬| 超碰在线电影| 伊人网在线免费| 国产美女主播一区| 亚洲乱码一区二区| 亚洲电影一区二区三区| 成人小视频免费观看| 99国内精品| 国产精品一区二区三区av麻|