浅谈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 相关文章推荐
如何阻止复制剪切和粘贴事件为了表单内容的安全
May 23 Javascript
通过length属性判断jquery对象是否存在
Oct 18 Javascript
JavaScript用JQuery呼叫Server端方法示例代码
Sep 03 Javascript
基于PHP和Mysql相结合使用jqGrid读取数据并显示
Dec 02 Javascript
JavaScript开发者必备的10个Sublime Text插件
Feb 27 Javascript
AngularJS基础 ng-keydown 指令简单示例
Aug 02 Javascript
vue中如何创建多个ueditor实例教程
Nov 14 Javascript
Vue中控制v-for循环次数的实现方法
Sep 26 Javascript
javascript中floor使用方法总结
Feb 02 Javascript
浅谈发布订阅模式与观察者模式
Apr 09 Javascript
vue实现购物车案例
May 30 Javascript
Vue+Element ui 根据后台返回数据设置动态表头操作
Sep 21 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中file_exists与is_file,is_dir的区别介绍
2012/09/12 PHP
奉献出一个封装的curl函数 便于调用(抓数据专用)
2013/07/22 PHP
discuz免激活同步登入代码修改方法(discuz同步登录)
2013/12/24 PHP
jQuery Tools tooltip使用说明
2012/07/14 Javascript
禁用键盘上的(全局)指定键兼容iE、Chrome、火狐
2013/05/14 Javascript
iframe的父子窗口之间的对象相互调用基本用法
2013/09/03 Javascript
JS过滤url参数特殊字符的实现方法
2013/12/24 Javascript
js弹出确认是否删除对话框
2014/03/27 Javascript
jQuery的one()方法用法实例
2015/01/19 Javascript
javascript中JSON对象与JSON字符串相互转换实例
2015/07/11 Javascript
浅谈javascript原型链与继承
2015/07/13 Javascript
怎么通过onclick事件获取js函数返回值(代码少)
2015/07/28 Javascript
使用Chart.js图表库制作漂亮的响应式表单
2015/10/28 Javascript
javascript添加前置0(补零)的几种方法
2017/01/05 Javascript
对vue里函数的调用顺序介绍
2018/03/17 Javascript
jQuery实现提交表单时不提交隐藏div中input的方法
2019/10/08 jQuery
微信小程序加载机制及运行机制图解
2019/11/27 Javascript
jQuery实现简易QQ聊天框
2020/02/10 jQuery
js操作两个json数组合并、去重,以及删除某一项元素
2020/09/22 Javascript
详解Python如何获取列表(List)的中位数
2016/08/12 Python
python安装requests库的实例代码
2019/06/25 Python
基于OpenCV的路面质量检测的实现
2020/11/04 Python
Python包资源下载路径报404解决方案
2020/11/05 Python
使用Python判断一个文件是否被占用的方法教程
2020/12/16 Python
HTML5中通过li-canvas轻松实现单图、多图、圆角图绘制,单行文字、多行文字等
2018/11/30 HTML / CSS
美国殿堂级滑板、冲浪、滑雪服装品牌:Volcom(钻石)
2017/04/20 全球购物
小学家长会邀请函
2014/01/23 职场文书
《影子》教学反思
2014/02/21 职场文书
2015年学校政教工作总结
2015/07/20 职场文书
情感电台广播稿
2015/08/18 职场文书
Python time库的时间时钟处理
2021/05/02 Python
Requests什么的通通爬不了的Python超强反爬虫方案!
2021/05/20 Python
SQL实现LeetCode(197.上升温度)
2021/08/07 MySQL
python实现层次聚类的方法
2021/11/01 Python
python神经网络学习 使用Keras进行简单分类
2022/05/04 Python