从Go工具到Vite插件:参考esbuild案例打造前端自动化部署神器

0 阅读3分钟

在前端工程化的现在,自动化的构建与部署直接决定了开发效率,常规生产环境有CI/CD流水线,而测试环境使用CI/CD流水线存在一下问题

  1. 因为CI/CD是服务端构建,而服务器的cpu能力相对较弱,打包速度也相对较慢。
  2. 因为测试环境存在频繁的bug发现、代码修改部署上传再到发现,短时间内可能存在高频次代码提交。

因此以上两点问题照旧在测试阶段存在效率问题

因此我使用go开发了一个自动压缩上传的程序

整体思路

程序整体思路并不难,就是使用go对打包后的产物进行代码压缩,然后以sftp上传至服务器,而这只需要在vite构建后自动执行既可,或者webpack构建完成后。

而js与go的交互只需通过node调用spawnapi启动go的进程既可,二者进程互相独立。

开发过程问题详细解

问题一:ESM与CommonJS

在package.json上这俩个个模式只是一行配置

    {
     "type": "module",//commonjs
    }

默认不填写为commonjs

  1. 二者语法
//commonjs
const os = require('os')
//esm
import os from 'os'
  1. comonjs 为动态执行,esm为静态执行
  2. Tree‑Shaking优化,由于esm为静态执行,可以支持,但commonjs不支持
  3. commonjs是值拷贝,如果导出是对象,那么a模块修改后b模块并不会动,esm相反

问题二:require.resolve

在将我开发的功能转为npm插件中,阅读esbuild源码当中发现大量使用require.resolve。 常规cjs当中使用require('xx')导入node_modules里面的包 而require.resolve就是解析该包的路径

console.log(require.resolve('axios)) /xxx/xxx/项目名/node_modules/axios/xxx

后面的会为package.json里面配置的main 这是这个包的入口文件。 在esm当中也有推荐使用 createRequire

import { createRequire } from "module";
const require = createRequire(import.meta.url);

问题三:关于package当中各种dependencies

在package当中dependencies有很多种,以esbuild当中的dependencies看

 {
  "optionalDependencies": {
    "@esbuild/aix-ppc64": "0.28.0",
    ...xx
  },
 }

这个optionalDependencies是可安装依赖。

当执行npm i的时候,你下载的依赖内存会有一个package记录他这个包所需要的依赖这个是走dependencies与devDependencies,当报错的时候npm i就会失败。

而optionalDependencies下载失败是不会停止,这就为esbuild配置实现了自动根据用户操作系统与cpu架构自行从npm仓库拉去自己想要的esbuild程序

而go开发的原生二进制程序只需要在package上写入os与cpu俩个属性就能让npm匹配当前用户的操作系统与cpu架构是否符合


"os": [
    "linux"
  ],
  "cpu": [
    "arm"
  ]
  //限制为linux的arm架构可以安装成功

问题四:关于下载失败的保底机制

在esbuild当中,存在一个如果你npm i执行后esbuild的二进制包没有下载失败的保底程序,就从新下载

async function checkAndPreparePackage() {

  const { pkg, subpath, isWASM } = pkgAndSubpathForCurrentPlatform(); //获取你电脑的操作系统与架构
  let binPath;
  try {
    binPath = require.resolve(`${pkg}/${subpath}`); 
    //如果npm i下载成功后,node_modules里这一段代码就会解析成功不会报错
  } catch (e) {
  
    binPath = downloadedBinPath(pkg, subpath); 
    //解析失败,准备下载二进制文件,这是获取需要放入的文件地址
    try {
      installUsingNPM(pkg, subpath, binPath);
    } catch (e2) {
      
      try {
        await downloadDirectlyFromNPM(pkg, subpath, binPath); //下载
      } catch (e3) {
        throw new Error(`Failed to install package "${pkg}"`);
      }
    }
  }
}
//检查
checkAndPreparePackage().then(() => {
  if (isToPathJS) {
    validateBinaryVersion(process.execPath, toPath);
  } else {
    validateBinaryVersion(toPath);
  }
});

而想让这个代码在npm i后执行只需要在package.json当中配置

 "scripts": {
    "postinstall": "node install.js"
  },

以上就是个人目前总结的东西!

也欢迎使用本人用go开发的sftp压缩上传的vite插件

www.npmjs.com/package/vit…

目前没有像esbuild那样存在如果在npm i下载失败的保底机制,正在深入研究