從0到1開源整合vue、react開發流的工具cli

近期開源了一個 cli 小工具:前端

  1. 抽離構建全流程,實現了構建與開發解耦;
  2. 能夠同時支持 vue/react 項目的開發與生產構建(主要由於本人 vue/react 生態用的會比較多);
  3. 支持項目快速初始化,目前僅引入了 4 個初始化模板,分別爲 react/vue 的 js 與 ts 版本,模板將會在後續逐步完成;
  4. 支持 umd 單獨打包公共模塊,好比合並 react/react-dom/react-router 爲一個通用包這種場景;

以上是目前場景支持,後續會逐步延展;
下面來分享下開發全流程,你們有興趣的話也能夠作一個本身的 cli 工具,有不對的地方請不吝指正;
煩請各位大佬給個贊,謝謝。vue

初始化

  1. npm init 初始化 package.jsonnode

  2. package.json 中幾個重要屬性說明react

    name:包名,用做以後發佈到 npm 惟一標識;
    version:發佈包版本號;
    bin:用來指定各個內部命令對應的可執行文件的位置。linux

{
 "name": "iwater", // 包名 iwater  "version": "0.0.1", // 發佈版本號 0.0.1  "description": "基於 react、vue 的 cli 整合工具",  "keywords": ["webpack", "vue", "react", "cli"],  "bin": {  "water": "bin/water", // 主命令 water  "water-create": "bin/water-create", // 初始化命令 water create  "water-dev": "bin/water-dev", // 開發環境命令 water dev  "water-prod": "bin/water-prod", // 生產構建命令 water prod  "water-umd": "bin/water-umd" // umd 打包命令 water umd  }  // ... } 複製代碼

編寫命令文件

目錄結構

.
├── package.json ## 描述文件 └─── bin  ├── water # 主命令入口  ├── water-create # 初始化入口  ├── water-dev # 開發環境入口  ├── water-prod # 生產環境入口  └── water-umd # umd 打包入口 複製代碼

npm link

此命令用做本地調試比較方便,代碼即改全局即生效
將命令映射到全局,實際上是建立了一個軟鏈接(快捷方式)到全局webpack

water 主入口

// 這個聲明比較重要,用於聲明 linux/unix 系統 shell 腳本查找 node 命令
#!/usr/bin/env node  // commander 用於定義命令聲明和接口 const program = require("commander");  program  // 版本  .version(require("../package").version)  // 命令映射  .usage(  `  water create  water dev  water prod -i -m [module] -e [env]  water umd -i`  )  // 描述信息  .description(  `Params:   dev:  -m [module] 模塊名稱  -i 是否打印詳細信息   prod:  -m [module] 模塊名稱  -i 是否打印詳細信息  -e [env] 環境變量   umd:  -i 是否打印詳細信息  `  )  // 命令映射  .command("create", "初始化項目")  .command("dev", "開發環境構建")  .command("prod", "生產環境構建")  .command("umd", "公共包構建");  // 解析命令參數 program.parse(process.argv); 複製代碼

這時便可在命令行輸入 water, 查看命令是否生效git

water
water

water create 項目模板初始化

#!/usr/bin/env node
 const { join } = require("path"); // 交互式命令行工具,用做命令選項問答 const { prompt } = require("inquirer"); const chalk = require("chalk");  const { copyFolder } = require("../lib/utils/file");  const developPath = process.cwd(); const waterPath = join(__dirname, ".."); const templatePathPrefix = "template";  // 定義命令行問答 prompt([  {  type: "input",  name: "name",  message: "項目名稱:",  default: "water-ui",  },  {  type: "list",  name: "language",  choices: ["react", "vue"],  message: "開發語言:",  default: "react",  },  {  type: "confirm",  name: "typescript",  message: "使用 Typescript:",  default: "Y",  }, ])  .then(({ name, typescript, language }) => {  // 問答解析  const templateName = `${language}${typescript ? "-ts" : ""}`;  const templatePath = join(waterPath, templatePathPrefix, templateName);  const toPath = join(developPath, name);   // 複製項目模板  copyFolder(templatePath, toPath);  console.log(chalk.green("> ") + "初始化完成");  })  .catch((error) => {  if (error.isTtyError) {  console.error("當前環境暫不支持");  // Prompt couldn't be rendered in the current environment  } else {  // Something else when wrong  console.error(error);  }  }); 複製代碼

water dev 開發模式構建

主要思路是抽取 webpack 公共配置,抽離到 cli 命令中統一構建和管理,再以子進程進行調用github

#!/usr/bin/env node
 const program = require("commander");  program  .usage("[options] -m")  // 定義參數解析  .option("-m, --module [module]", "模塊名稱")  .parse(process.argv);  const { join } = require("path"); // 子進程 const { spawn } = require("child_process");  // 這裏的思路是用子進程調用 webpack-dev-server 去打開開發者模式的構建 // 1. 子進程調用 webpack-dev-server // 2. webpack-dev-server 調取配置好的配置文件,這裏的重點仍是 webpack 的配置文件 // 3. 啓動監聽 const build = spawn(  "node",  [  `${join(  __dirname,  "../node_modules/webpack-dev-server/bin/webpack-dev-server.js"  )}`,  "--watch",  "--config",  `${join(__dirname, `../lib/build/webpack.dev.js`)}`,  program.module ? ` --env.name ${program.module}` : "",  ],  {  stdio: "inherit",  shell: true,  cwd: process.cwd(),  } );  build.on("error", (error) => console.error(error));  build.on("exit", (code) => {  console.log("exit", code);  process.exitCode = code;  process.exit(); }); 複製代碼

water prod -i 生產環境構建

主要思路是抽離公共配置文件,直接調用 webpack 去啓動構建web

#!/usr/bin/env node
 const { red } = require("chalk"); const program = require("commander");  program  .usage("[options] -i -m [module] -e [env]")  .option("-m, --module [module]", "模塊名稱")  .option("-i, --info", "是否打印記錄")  .option("-e, --env [env]", "發佈環境[dev, uat, prod, front...]")  .parse(process.argv);  const { getApp, getPackageInfo } = require("../lib/utils/getConfig"); const appConfig = getApp(program.module || null);  if (!appConfig) {  console.error(red("> 缺乏 app 配置"));  return; }  const webpack = require("webpack"); const isInfo = program.info; // 發佈環境標識,用做區分不一樣環境的 bucket const env = program.env;  webpackConfig = require(`../lib/build/webpack.prod.js`)({  ...appConfig, });  const buildStamp = Date.now();  webpack(webpackConfig, async (err, stats) => {  if (err || stats.hasErrors()) {  if (err) {  console.error(red(err.stack || err));  err.details && console.error(red(err.details));  return;  }   stats.hasErrors() &&  console.error(stats.toString({ colors: true, chunks: false }));   console.log("\n> 構建異常 \n");  } else {  isInfo && console.warn(stats.toString({ colors: true, chunks: false }));   console.log(`\n> 構建完成,耗時 ${Date.now() - buildStamp} ms`);  } }); 複製代碼

water umd -i umd 打包入口

主要思路是抽離公共配置文件,直接調用 webpack 去啓動構建typescript

#!/usr/bin/env node
 const { red } = require("chalk"); const program = require("commander");  program  .usage("[options] -i")  .option("-m, --module [module]", "模塊名稱")  .option("-i, --info", "是否打印記錄")  .parse(process.argv);  const { getApp } = require("../lib/utils/getConfig"); const appConfig = getApp(program.module || null);  if (!appConfig) {  console.error(red("> 缺乏 app 配置"));  return; }  const webpack = require("webpack"); const isInfo = program.info;  webpackConfig = require(`../lib/build/webpack.umd.js`)({  ...appConfig, });  const buildStamp = Date.now();  webpack(webpackConfig, async (err, stats) => {  if (err || stats.hasErrors()) {  if (err) {  console.error(red(err.stack || err));  err.details && console.error(red(err.details));  return;  }   stats.hasErrors() &&  console.error(stats.toString({ colors: true, chunks: false }));   console.log("\n> 構建異常 \n");  } else {  isInfo && console.warn(stats.toString({ colors: true, chunks: false }));   console.log(`\n> 構建完成,耗時 ${Date.now() - buildStamp} ms`);  } }); 複製代碼

發佈到 npm

  1. 首先註冊一個 npm 帳戶
  2. npm login 用註冊的帳密進行登陸
  3. npm publish 發佈到 npm,每次發佈記得修改 package.json 版本號
  4. 發佈成功後便可 npm i -g iwater 安裝到本地

總結

以上是 cli 開發的核心流程,water 的核心思想:

  1. 整合構建流程到工具,全部項目無需再關注構建;
  2. 統一 vue/react 項目構建和分發,構建產物統一;
  3. 拓展 cli 便可達成全局拓展;

更多細節,請移步Github,給個star謝謝
歡迎關注「前端藝匠」公衆號,發佈大前端領域文章,關注不走丟,謝謝

前端藝匠
前端藝匠
相關文章
相關標籤/搜索