TypeScript 用 Webpack/ts-node 运行的配置记录

公司项目代码是用 TypeScript 写的, 中间遇到有些代码不要放到 Node 里面去跑.
具体场景一些路由配置, 比较大的一块 JSON 数据定义在 TypeScript 里.
我另外有增长脚本, 基于这些 JSON 数据用来生成切换路由的函数.
这就须要运行 TypeScript 了, 并且可能包含一些额外的业务代码.前端

首先 Node 运行 TypeScript 有提供 ts-node 用来处理.
ts-node 会先编译 TypeScript 代码到 JavaScript, 再调用 Node 运行.
不过这个办法有一些问题, 一个是 TypeScript 定义的路径配置不成功,
另外一个问题更麻烦点, 就是引用到的其余的浏览器端代码由于触发运行而引发报错.node

Webpack 打包 TypeScript Node 代码

我先想到了一个相对省事的方案, 就是用 Webpack 对 TypeScript 进行打包.
打包完成之后输出 JavaScript 代码. 而浏览器代码打包进去, 但不必定运行.
因为 TypeScript 配置在 Webpack 当中引用有比较成熟的方案, 整个配置也写好:react

module.exports = {
  mode: "development",
  target: "node",
  entry: ["./example/gen-router.ts"],
  output: {
    filename: "gen-router.js",
    path: path.join(__dirname, "../", distFolder),
  },
  devtool: "none",
  module: {
    rules: [
      // 正常的 TypeScript 编译方式, 我这份是拷贝的.
      {
        test: /\.tsx?$/,
        exclude: [/node_modules/, path.join(__dirname, "scripts")],
        use: [
          { loader: "cache-loader" },
          {
            loader: "thread-loader",
            options: {
              workers: require("os").cpus().length - 1,
            },
          },
          {
            loader: "ts-loader",
            options: {
              happyPackMode: true,
              transpileOnly: true,
            },
          },
        ],
      },
    ],
  },
  // Node 模块, 写在 external 里面代表不须要进行打包. 注意 commonjs 前缀
  externals: {
    prettier: "commonjs prettier",
    "@jimengio/router-code-generator": "commonjs @jimengio/router-code-generator",
    fs: "commonjs fs",
    path: "commonjs path",
  },
  resolve: {
    extensions: [".tsx", ".ts", ".js"],
    modules: [path.join(__dirname, "example"), "node_modules"],

    // 引用 Plugin 用于读取 tsconfig.json 文件的配置
    plugins: [new TsconfigPathsPlugin({ configFile: path.join(__dirname, "../tsconfig.json") })],
  },
};

基于这个配置打包之后, TypeScript 的代码被打包好, 而且引用响应的 Node 模块.
运行就知足需求了.git

这个方式对于其余的服务端渲染的 TypeScript 代码打包也是相似的.
一些特殊的依赖若是很差处理, 能够放在 Webpack 当中进行打包和映射, 获得 js.github

ts-node 运行

Webpack 配置相对直接运行 TypeScript 来讲会复杂一点, 因此仍是 ts-node 简单.
在依赖少的项目当中, 我改为了用 ts-node 来进行编译运行. 配置以下json

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true,
    "sourceMap": true,
    "noImplicitAny": false,
    "noImplicitThis": true,
    "strictNullChecks": false,
    "moduleResolution": "node",

    // Node 当前尚未支持直接运行 import/export 语法, 须要编译到 CommonJS
    "module": "commonjs",

    "target": "es2016",
    "jsx": "react",
    "lib": ["es2016"],
    "types": ["node"],
    "baseUrl": "./example/",
    "paths": {
      "models": ["./example/models"]
    },
    "plugins": []
  }
}

其实主要修改就 commonjs 那一行, 而后就是加上参数运行浏览器

ts-node -P tsconfig-node.json -r tsconfig-paths/register example/gen-router.ts

注意命令当中的 tsconfig-paths. 这里的 -r 是指定 register.
ts-node 是先进行编译再运行的, 可是引用的路径没有全都替换掉.
好比我在 tsconfig.json 里设置了 baseUrl 而后内部引用是简写的, a/b/c,
拿到 Node 自己去运行的时候是不知道这个 a/b/c 对应到哪里,
因此 tsconfig-paths/register 就提供 Node 运行时的方案, 动态查找依赖.
至少这样 Node register 改写之后, 查找模块就能正确进行了.app

其余

另外 TypeScript 编译 import 语法时会产生一个 .default 属性.
对于 CommonJS 的模块, 这个 .default 属性是多余的. 因此引用的写法要作调整.函数

import * as fs from "fs";
import * as path from "path";
import * as prettier from "prettier";

这个可能跟 tsconfig.json 里其余的配置有关联, 我没继续深挖.工具

总体的代码参考 https://github.com/jimengio/meson-form/pull/62/files


其余关于积梦前端的模块和工具能够查看咱们的 GitHub 主页 https://github.com/jimengio .
目前团队正在扩充, 招聘文档见 GitHub 仓库 https://github.com/jimengio/h... .

相关文章
相关标签/搜索