浅谈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入门学习书籍推荐
Jun 12 Javascript
event.srcElement 用法笔记e.target
Dec 18 Javascript
JQuery的read函数与js的onload不同方式实现
Mar 18 Javascript
javascript的document.referrer浏览器支持、失效情况总结
Jul 18 Javascript
js的toLowerCase方法用法实例
Jan 27 Javascript
举例讲解jQuery中可见性过滤选择器的使用
Apr 18 Javascript
domReady的实现案例
Nov 23 Javascript
JS基于面向对象实现的拖拽功能示例
Dec 20 Javascript
vue动态路由实现多级嵌套面包屑的思路与方法
Aug 16 Javascript
JS禁止浏览器右键查看元素或按F12审查元素自动关闭页面示例代码
Sep 07 Javascript
p5.js入门教程之键盘交互
Mar 19 Javascript
js实现点击展开隐藏效果(实例代码)
Sep 28 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
要会喝咖啡也要会知道咖啡豆
2021/03/03 咖啡文化
php环境套包 dedeampz 伪静态设置示例
2014/03/26 PHP
PHP+redis实现添加处理投票的方法
2015/11/14 PHP
thinkPHP5框架实现多数据库连接,跨数据连接查询操作示例
2019/05/29 PHP
jQuery的三种$()
2009/12/30 Javascript
解析javascript 数组以及json元素的添加删除
2013/06/26 Javascript
AngularJS实现根据变量改变动态加载模板的方法
2016/11/04 Javascript
Vue.js组件tree实现省市多级联动
2016/12/02 Javascript
Jquery实现跨域异步上传文件总结
2017/02/03 Javascript
js 简易版滚动条实例(适用于移动端H5开发)
2017/06/26 Javascript
bootstrap treeview 扩展addNode方法动态添加子节点的方法
2017/11/21 Javascript
[55:35]VGJ.S vs Mski Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
python代码制作configure文件示例
2014/07/28 Python
Python实现的一个找零钱的小程序代码分享
2014/08/25 Python
Python中List.count()方法的使用教程
2015/05/20 Python
Python中列表、字典、元组数据结构的简单学习笔记
2016/03/20 Python
Python 安装setuptools和pip工具操作方法(必看)
2017/05/22 Python
基于Python函数的作用域规则和闭包(详解)
2017/11/29 Python
python3.6连接MySQL和表的创建与删除实例代码
2017/12/28 Python
Python之ReportLab绘制条形码和二维码的实例
2018/01/15 Python
OpenCV-Python 摄像头实时检测人脸代码实例
2019/04/30 Python
Python类中的魔法方法之 __slots__原理解析
2019/08/26 Python
python读取Excel表格文件的方法
2019/09/02 Python
Python下应用opencv 实现人脸检测功能
2019/10/24 Python
虚拟环境及venv和virtualenv的区别说明
2021/02/05 Python
Roots加拿大官网:加拿大休闲服饰品牌
2016/10/24 全球购物
单位实习证明怎么写
2014/01/17 职场文书
管理提升方案
2014/06/04 职场文书
公司总经理助理岗位职责
2014/07/09 职场文书
中药学专业毕业生推荐信
2014/07/10 职场文书
授权委托书协议书
2014/10/16 职场文书
2015商场元旦促销活动策划方案
2014/12/09 职场文书
2016教师廉洁教育心得体会
2016/01/13 职场文书
2016暑期社会实践心得体会范文
2016/01/14 职场文书
《自己的花是让别人看的》教学反思
2016/02/19 职场文书
python神经网络 使用Keras构建RNN训练
2022/05/04 Python