浅谈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语句可以不以;结尾的烦恼
Mar 08 Javascript
JavaScript 继承详解 第一篇
Aug 30 Javascript
深入理解JavaScript定时机制
Oct 29 Javascript
jquery获取table中的某行全部td的内容方法
Mar 08 Javascript
php显示当前文件所在的文件以及文件夹所有文件以树形展开
Dec 13 Javascript
浅析在javascript中创建对象的各种模式
May 06 Javascript
前端js文件合并的三种方式推荐
May 19 Javascript
three.js实现围绕某物体旋转
Jan 25 Javascript
WebSocket实现简单客服聊天系统
May 12 Javascript
react用Redux中央仓库实现一个todolist
Sep 29 Javascript
微信小程序之导航滑块视图容器功能的实现代码(简单两步)
Jun 19 Javascript
uniapp引入支付宝原生扫码插件步骤详解
Jul 23 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
xml在joomla表单中的应用详解分享
2012/07/19 PHP
php程序总是提示验证码输入有误解决方案
2015/01/07 PHP
详解PHP对象的串行化与反串行化
2016/01/24 PHP
基于jQuery的日期选择控件
2009/10/27 Javascript
JQuery中对服务器控件 DropdownList, RadioButtonList, CheckboxList的操作总结
2011/06/28 Javascript
extjs tabpanel限制选项卡数量实现思路及代码
2013/04/02 Javascript
含有CKEditor的表单如何提交
2014/01/09 Javascript
jquery中$.post()方法的简单实例
2014/02/04 Javascript
jquery跟js初始化加载的多种方法及区别介绍
2014/04/02 Javascript
使用JavaScript进行进制转换将字符串转换为十进制
2014/09/21 Javascript
javascript中var的重要性分析
2015/02/11 Javascript
Jquery判断radio、selelct、checkbox是否选中及获取选中值方法总结
2015/04/15 Javascript
JavaScript中的anchor()方法使用详解
2015/06/08 Javascript
每天一篇javascript学习小结(面向对象编程)
2015/11/20 Javascript
轮播图组件js代码
2016/08/08 Javascript
less简单入门(CSS 预处理语言)
2017/03/08 Javascript
node.js程序作为服务并在windows下开机自启动(用forever)
2017/03/29 Javascript
jQuery解析json格式数据示例
2018/09/01 jQuery
微信小程序swiper实现文字纵向轮播提示效果
2020/01/21 Javascript
基于JQuery和DWR实现异步数据传递
2020/10/16 jQuery
为Python的web框架编写MVC配置来使其运行的教程
2015/04/30 Python
Python中__new__与__init__方法的区别详解
2015/05/04 Python
Python读取键盘输入的2种方法
2015/06/16 Python
Python2.x版本中基本的中文编码问题解决
2015/10/12 Python
python中的闭包函数
2018/02/09 Python
python爬虫实现POST request payload形式的请求
2020/04/30 Python
Python 程序员必须掌握的日志记录
2020/08/17 Python
总结python 三种常见的内存泄漏场景
2020/11/20 Python
编译 pycaffe时报错:fatal error: numpy/arrayobject.h没有那个文件或目录
2020/11/29 Python
加拿大鞋子连锁店:Town Shoes
2016/09/26 全球购物
维氏瑞士军刀英国网站:Victorinox英国
2019/07/04 全球购物
车工岗位职责
2013/11/26 职场文书
化学教师教学反思
2014/01/17 职场文书
离婚起诉书范文2015
2015/05/19 职场文书
红色影片观后感
2015/06/18 职场文书
医院保洁员管理制度
2015/08/05 职场文书