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


Posted in Javascript onOctober 11, 2019

公司项目代码是用 TypeScript 写的, 中间遇到有些代码不要放到 Node 里面去跑.

具体场景一些路由配置, 比较大的一块 JSON 数据定义在 TypeScript 里.

我另外有增加脚本, 基于这些 JSON 数据用来生成切换路由的函数.

这就需要运行 TypeScript 了, 而且可能包含一些额外的业务代码.

首先 Node 运行 TypeScript 有提供 ts-node 用来处理.

ts-node 会先编译 TypeScript 代码到 JavaScript, 再调用 Node 运行.

不过这个办法有一些问题, 一个是 TypeScript 定义的路径配置不成功,

另一个问题更麻烦点, 就是引用到的其他的浏览器端代码因为触发运行而引起报错.

Webpack 打包 TypeScript Node 代码

我先想到了一个相对省事的方案, 就是用 Webpack 对 TypeScript 进行打包.

打包完成以后输出 JavaScript 代码. 而浏览器代码打包进去, 但不一定运行.

由于 TypeScript 配置在 Webpack 当中引用有比较成熟的方案, 整个配置也写好:

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 模块.

运行就满足需求了.

这个方式对于其他的服务端渲染的 TypeScript 代码打包也是类似的.

一些特殊的依赖如果不好处理, 可以放在 Webpack 当中进行打包和映射, 得到 js.

ts-node 运行

Webpack 配置相对直接运行 TypeScript 来说会复杂一点, 所以还是 ts-node 简单.

在依赖少的项目当中, 我改成了用 ts-node 来进行编译运行. 配置如下

{
 "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 改写以后, 查找模块就能正确进行了.

其他

另外 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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
在JavaScript中通过URL传递汉字的方法
Apr 09 Javascript
用javascript实现自定义标签
May 08 Javascript
JavaScript实现维吉尼亚(Vigenere)密码算法实例
Nov 22 Javascript
用Jquery.load载入页面实现局部刷新
Jan 22 Javascript
JavaScript实现常用二级省市级联下拉列表的方法
Mar 25 Javascript
javascript用函数实现对象的方法
May 14 Javascript
BootStrap modal模态弹窗使用小结
Oct 26 Javascript
jquery css实现邮箱自动补全
Nov 14 Javascript
Windows系统下安装Node.js的步骤图文详解
Nov 15 Javascript
Vue单文件组件的如何使用方式介绍
Jul 28 Javascript
JS实现预加载视频音频/视频获取截图(返回canvas截图)
Oct 09 Javascript
vue解决跨域路由冲突问题思路解析
Nov 03 Javascript
详解vue 自定义组件使用v-model 及探究其中原理
Oct 11 #Javascript
JsonProperty 的使用方法详解
Oct 11 #Javascript
vue element upload组件 file-list的动态绑定实现
Oct 11 #Javascript
解决Idea、WebStorm下使用Vue cli脚手架项目无法使用Webpack别名的问题
Oct 11 #Javascript
微信小程序 点击切换样式scroll-view实现代码实例
Oct 11 #Javascript
vue控制多行文字展开收起的实现示例
Oct 11 #Javascript
这15个Vue指令,让你的项目开发爽到爆
Oct 11 #Javascript
You might like
php实现的后台表格分页功能示例
2017/10/23 PHP
Thinkphp框架+Layui实现图片/文件上传功能分析
2020/02/07 PHP
zTree插件之单选下拉菜单实例代码
2013/11/07 Javascript
node.js中的emitter.emit方法使用说明
2014/12/10 Javascript
5个数组Array方法: indexOf、filter、forEach、map、reduce使用实例
2015/01/29 Javascript
jquery SweetAlert插件实现响应式提示框
2015/08/18 Javascript
浅析$.getJSON异步请求和同步请求
2016/06/06 Javascript
纯JS前端实现分页代码
2016/06/21 Javascript
AngularJs 最新验证手机号码的实例,成功测试通过
2017/11/26 Javascript
Angular5中状态管理的实现
2018/09/03 Javascript
React降级配置及Ant Design配置详解
2018/12/27 Javascript
NestJs 静态目录配置详解
2019/03/12 Javascript
java遇到微信小程序 "支付验证签名失败" 问题解决
2019/12/22 Javascript
js实现简易拖拽的示例
2020/10/26 Javascript
Python中time模块和datetime模块的用法示例
2016/02/28 Python
python实现二维数组的对角线遍历
2019/03/02 Python
NumPy 数组使用大全
2019/04/25 Python
如何使用django的MTV开发模式返回一个网页
2019/07/22 Python
使用python脚本自动创建pip.ini配置文件代码实例
2019/09/20 Python
python GUI库图形界面开发之PyQt5树形结构控件QTreeWidget详细使用方法与实例
2020/03/02 Python
Python正则表达式如何匹配中文
2020/05/27 Python
Python修改DBF文件指定列
2020/12/19 Python
英国电子产品购物网站:Tech in the basket
2019/11/08 全球购物
泰国排名第一的家居用品中心:HomePro
2020/11/18 全球购物
建筑工程管理专业自荐信范文
2013/12/28 职场文书
马云的职业生涯规划之路
2014/01/01 职场文书
文明家庭先进事迹材
2014/01/27 职场文书
秋游活动策划方案
2014/02/16 职场文书
静心口服夜广告词
2014/03/20 职场文书
国际贸易专业求职信
2014/06/04 职场文书
汽车检测与维修专业求职信
2014/07/04 职场文书
2014年网管工作总结
2014/12/11 职场文书
埃及王子观后感
2015/06/16 职场文书
Win11安装受阻怎么办? Windows11安装问题与解决方案汇总
2021/11/21 数码科技
uni-app 微信小程序授权登录的实现步骤
2022/02/18 Javascript
 python中的元类metaclass详情
2022/05/30 Python