浅谈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 相关文章推荐
如何实现iframe(嵌入式帧)的自适应高度
Jul 26 Javascript
Code: write(s,d) 输出连续字符串
Aug 19 Javascript
js设置文本框中焦点位置在最后的示例代码(简单实用)
Mar 04 Javascript
JS嵌套函数调用上下文的问题解决
Mar 26 Javascript
jquery获取html元素的绝对位置和相对位置的方法
Jun 20 Javascript
Bootstrap滚动监听(Scrollspy)插件详解
Apr 26 Javascript
利用jQuery的动画函数animate实现豌豆发射效果
Aug 28 Javascript
使用vue.js实现联动效果的示例代码
Jan 10 Javascript
JS实现带动画的回到顶部效果
Dec 28 Javascript
JS异步处理的进化史深入讲解
Aug 25 Javascript
对vuex中store和$store的区别说明
Jul 24 Javascript
原生JavaScript实现贪吃蛇游戏
Nov 04 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
苏联队长,苏联超人蝙蝠侠,这些登场的“山寨”英雄真的很严肃
2020/04/09 欧美动漫
分享PHP源码批量抓取远程网页图片并保存到本地的实现方法
2015/12/01 PHP
PHP静态方法和静态属性及常量属性的区别与介绍
2019/03/22 PHP
了解了这些才能开始发挥jQuery的威力
2013/10/10 Javascript
Area 区域实现post提交数据的js写法
2014/04/22 Javascript
选择复选框按钮置灰否则按钮可用
2014/05/22 Javascript
浅谈JavaScript中的字符编码转换问题
2015/07/07 Javascript
基于jQuery实现仿微博发布框字数提示
2016/07/27 Javascript
百度多文件异步上传控件webuploader基本用法解析
2016/11/07 Javascript
js每隔两秒输出数组中的一项(实例)
2017/05/28 Javascript
微信小程序实现鼠标拖动效果示例
2017/12/01 Javascript
JS通过位运算实现权限加解密
2018/08/14 Javascript
ES6 class类链式继承,实例化及react super(props)原理详解
2020/02/15 Javascript
手把手教您实现react异步加载高阶组件
2020/04/07 Javascript
Python基于Socket实现的简单聊天程序示例
2017/08/05 Python
对python 各种删除文件失败的处理方式分享
2018/04/24 Python
python执行精确的小数计算方法
2019/01/21 Python
Python基于滑动平均思想实现缺失数据填充的方法
2019/02/21 Python
python multiprocessing模块用法及原理介绍
2019/08/20 Python
python ubplot使用方法解析
2020/01/10 Python
Python实现桌面翻译工具【新手必学】
2020/02/12 Python
TensorBoard 计算图的查看方式
2020/02/15 Python
python交互模式基础知识点学习
2020/06/18 Python
什么是Python包的循环导入
2020/09/08 Python
2020年10款优秀的Python第三方库,看看有你中意的吗?
2021/01/12 Python
Python命令行参数argv和argparse该如何使用
2021/02/08 Python
使用canvas实现黑客帝国数字雨效果
2020/01/02 HTML / CSS
html5 datalist 选中option选项后的触发事件
2020/03/05 HTML / CSS
党员承诺书内容
2014/03/26 职场文书
学习型党组织心得体会
2014/09/12 职场文书
副检察长四风问题对照检查材料思想汇报
2014/10/07 职场文书
小浪底导游词
2015/02/12 职场文书
学校推普周活动总结
2015/05/07 职场文书
2015年度环卫处工作总结
2015/07/24 职场文书
PHP实现rar解压读取扩展包小结
2021/06/03 PHP
详解Python函数print用法
2021/06/18 Python