浅谈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 相关文章推荐
Jquery Ajax.ashx 高效分页实现代码
Oct 20 Javascript
jQuery Masonry瀑布流插件使用详解
Nov 17 Javascript
仿JQuery输写高效JSLite代码的一些技巧
Jan 13 Javascript
jquery手风琴特效插件
Feb 04 Javascript
JS 设置Cookie 有效期 检测cookie
Jun 15 Javascript
关于js中的鼠标事件总结
Jul 11 Javascript
最全正则表达式总结:验证QQ号、手机号、Email、中文、邮编、身份证、IP地址等
Aug 16 Javascript
为输入框加入数字js校验代码分享
Nov 02 Javascript
vue.js实现只弹一次弹框
Jan 29 Javascript
微信小程序中使用wxss加载图片并实现动画效果
Aug 13 Javascript
使用VUE+iView+.Net Core上传图片的方法示例
Jan 04 Javascript
微信小程序发送短信验证码完整实例
Jan 07 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
一个域名查询的程序
2006/10/09 PHP
php删除文件夹及其文件夹下所有文件的函数代码
2013/01/23 PHP
PHP实现即时输出、实时输出内容方法
2015/05/27 PHP
PHP7之Mongodb API使用详解
2015/12/26 PHP
phpcms中的评论样式修改方法
2016/10/21 PHP
Laravel 错误提示本地化的实现
2019/10/22 PHP
php慢查询日志和错误日志使用详解
2021/02/27 PHP
JavaScript中实现块作用域的方法
2010/04/01 Javascript
关于可运行代码无法正常执行的使用说明
2010/05/13 Javascript
ajax中get和post的说明及使用与区别
2012/12/23 Javascript
删除select中所有option选项jquery代码
2013/08/12 Javascript
jQuery点击自身以外地方关闭弹出层的简单实例
2013/12/24 Javascript
获取中文字符串的实际长度代码
2014/06/05 Javascript
JavaScript替换当前页面的方法
2015/04/03 Javascript
AngularJS整合Springmvc、Spring、Mybatis搭建开发环境
2016/02/25 Javascript
NodeJS设计模式总结【单例模式,适配器模式,装饰模式,观察者模式】
2017/09/06 NodeJs
vue click.stop阻止点击事件继续传播的方法
2018/09/04 Javascript
JavaScript模板引擎原理与用法详解
2018/12/24 Javascript
VUE v-model表单数据双向绑定完整示例
2019/01/21 Javascript
如何使用CSS3和JQuery easing 插件制作绚丽菜单
2019/06/18 jQuery
Vue.js递归组件实现组织架构树和选人功能
2019/07/04 Javascript
Vue 使用beforeEach实现登录状态检查功能
2019/10/31 Javascript
express异步函数异常捕获示例详解
2020/11/30 Javascript
Python算法之栈(stack)的实现
2014/08/18 Python
Android 兼容性问题:java.lang.UnsupportedOperationException解决办法
2017/03/19 Python
Python3直接爬取图片URL并保存示例
2019/12/18 Python
pycharm运行程序时看不到任何结果显示的解决
2020/02/21 Python
金讯Java笔试题目
2013/06/18 面试题
兼职学生的自我评价
2013/11/24 职场文书
2014年开学第一课活动方案
2014/03/06 职场文书
群众路线对照检查材料思想汇报怎么写
2014/09/18 职场文书
服务员态度差检讨书
2014/10/28 职场文书
李强优秀员工观后感
2015/06/16 职场文书
认识实习感想
2015/08/10 职场文书
2016年六一文艺汇演开幕词
2016/03/04 职场文书
52条SQL语句教你性能优化
2021/05/25 MySQL