使用Gulp优化构建流程

2023年 8月 22日 67.5k 0

故事背景

最近我将客户端项目(electron开发)从JavaScript全部迁移到了Typescript,由此产生了以下几个问题:

  • Typescript如何编译成JavaScript
  • electron无法直接使用ts文件作为开发环境的启动入口,也不能使用ts文件作为打包入口;所以必须将Ts编译成Js

  • JavaScript语法兼容
  • 将Ts文件编译成Js文件之后,需将其中的高级语法编译成兼容性强的低级语法,这个过程需使用Babel

  • electron启动入口寻找
  • 需要指定electron启动开发环境或者打包的入口路径

    改进前的解决方案

    使用嵌套的scripts命令以及rimraf实现↓↓↓

    以启动开发环境为例:

  • 需先使用tsc --outDir runtime_tmp将Typescript编译成JavaScript; 由Ts编译得到的Js代码放到 runtime_tmp这个临时目录下面;

  • 然后使用npx babel ./runtime_tmp --out-dir ./runtime 这一步将runtime_tmp目录下的高级Js语法转化成低级Js语法并放到runtime目录下

  • 最后再删除中间文件./runtime_tmp

  • 到这里完成源代码的构建,最后还要使用electron ./runtime启动开发环境。

    scripts命令如下所示:

  •     "prev": "tsc --outDir runtime_tmp && npx babel ./runtime_tmp --out-dir ./runtime && rimraf ./runtime_tmp",
        "start": "yarn prev && cross-env NODE_ENV=development electron ./runtime",
    

    这里用到了cross-env和rimraf 两个库文件。使用rimraf是为了保证在不同的os下都能够成功的删除临时目录,直接使用shell命令可能会报错。

    问题在于:上述的scripts脚本非常难阅读,增加不少的心智负担。于是我使用gulp构建自动化的工作流程,如下所示:

    改进后的解决方案:

    使用gulp构建工具的流来设置打包路线,从而使构建过程更加清晰

    安装依赖并创建gulpfile.js

    
    touch gulpfile.js
    
    yarn add -D gulp gulp-typescript gulp-babel gulp-exec @types/gulp @types/gulp-typescript @types/gulp-babel @types/gulp-exec
    
    

    gulpfile.js中的内容为:

    
    // gulpfile.js
    
    const gulp = require('gulp');
    
    const ts = require('gulp-typescript');
    
    const babel = require('gulp-babel');
    
    const {
    
        series
    
    } = require('gulp');
    
    const exec = require('gulp-exec');
    
     
    
    // 将ts编译成js
    
    function compileTypeScript() {
    
        const tsProject = ts.createProject('tsconfig.json');
    
        return tsProject.src()
    
            .pipe(tsProject()) // ts => js
    
            .pipe(babel()) // js => js
    
            .pipe(gulp.dest('runtime'));
    
    }
    
     
    
    // 开发
    
    function dev() {
    
        const tsProject = ts.createProject('tsconfig.json');
    
        return tsProject.src()
    
            .pipe(tsProject())
    
            .pipe(babel())
    
            .pipe(gulp.dest('runtime'))
    
            .pipe(exec('cross-env NODE_ENV=development electron ./runtime')); // 执行shell脚本
    
    }
    
     
    
    // 打包
    
    function build() {
    
        const tsProject = ts.createProject('tsconfig.json');
    
        return tsProject.src()
    
            .pipe(tsProject())
    
            .pipe(babel())
    
            .pipe(gulp.dest('runtime'))
    
            .pipe(exec('electron-builder'));
    
    }
    
     
    
    gulp.task('compile', series(compileTypeScript));
    
    gulp.task('dev', series(dev));
    
    gulp.task('build', series(build));
    
     
    
    // 默认导出是编译,也就是ts=>js的结果
    
    exports.default = series(
    
        compileTypeScript,
    
    );
    
    

    package.json中的脚本相应改成:

    
         "compile": "npx gulp",
    
         "start": "npx gulp dev",
    
         "dist": "npx gulp build",
    
    

    要点

    在使用.pipe(tsProject()).pipe(babel())的时候没有传入命令行参数,所以必要的参数需要在tsconfig.json和babel.config.js中提前配置好(主要是配置每一步输出文件目录和下一步的入口目录)

    electron入口问题

  • 在dev函数中,通过.pipe(exec('cross-env NODE_ENV=development electron ./runtime'));制定了yarn start也就是npx gulp dev运行时的入口目录为**./runtime**,这样就解决了启动开发环境时候electron找到入口的问题。

  • 解决electron打包时的入口问题,需要在package.json中配置build字段:

  • "build": {

    "appId": "***",
    
    "productName": "***",
    
    "directories": {
    
      "output": "***"
    
    },
    
    "files": [
    
      {
    
        "from": "runtime/",
    
        "to": "src/"
    
      },
    
      "*/**",
    
      "**/*",
    
      "!src/"
    
    ],
    
    "extraResources": [
    
      {
    
        "from": "***",
    
        "to": "***"
    
      }
    
    ],
    
    "asar": true,
    
    "win": {
    
      "icon": "***",
    
      "target": "dir",
    
      "requestedExecutionLevel": "requireAdministrator"
    
    },
    
    "linux": {
    
      "target": "dir"
    
    }
    

    },

    其中的关键点在于配置build.files.from为runtime, 也就是babel的输出目录。

    结论

    使用gulp之后的构建流程变得非常简洁,并且容易阅读,可维护性大大增强。

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论