浅谈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动态给table添加、删除行 改进版
Jan 19 Javascript
jQuery.Validate验证库的使用介绍
Apr 26 Javascript
浅谈javascript六种数据类型以及特殊注意点
Dec 20 Javascript
JavaScript中合并数组的N种方法
Sep 16 Javascript
Node.js模块封装及使用方法
Mar 06 Javascript
只需五句话搞定JavaScript作用域(经典)
Jul 26 Javascript
EasyUI的DataGrid每行数据添加操作按钮的实现代码
Aug 22 Javascript
JS获取数组中出现次数最多及第二多元素的方法
Oct 27 Javascript
Vue.js与 ASP.NET Core 服务端渲染功能整合
Nov 16 Javascript
浅谈vue-cli 3.0.x 初体验
Apr 11 Javascript
JS实现电商商品展示放大镜特效
Jan 07 Javascript
JS如何判断对象是否包含某个属性
Aug 29 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
php 类中的常量、静态属性、非静态属性的区别
2017/04/09 PHP
PHP如何将图片文件上传到另外一台服务器上
2019/08/26 PHP
解决windows上php xdebug 无法调试的问题
2020/02/19 PHP
LBS blog sql注射漏洞[All version]-官方已有补丁
2007/08/26 Javascript
鼠标滑上去后图片放大浮出效果的js代码
2011/05/28 Javascript
jQuery中将函数赋值给变量的调用方法
2012/03/23 Javascript
jquery使用$(element).is()来判断获取的tagName
2014/08/24 Javascript
js阻止浏览器默认行为触发的通用方法(推荐)
2016/05/15 Javascript
JavaScript编写Chrome扩展实现与浏览器的交互及时间通知
2016/05/16 Javascript
jQuery简单创建节点的方法
2016/09/09 Javascript
jquery事件绑定解绑机制源码解析
2016/09/19 Javascript
jQuery实现页面滚动时智能浮动定位
2017/01/08 Javascript
js仿小米手机上下滑动效果
2017/02/05 Javascript
20170918 前端开发周报之JS前端开发必看
2017/09/18 Javascript
JavaScript+H5实现微信摇一摇功能
2018/05/23 Javascript
用element的upload组件实现多图片上传和压缩的示例代码
2019/02/12 Javascript
Layui实现带查询条件的分页
2019/07/27 Javascript
Vue 打包体积优化方案小结
2020/05/20 Javascript
python简单分割文件的方法
2015/07/30 Python
Python文件处理
2016/02/29 Python
使用Python的Tornado框架实现一个Web端图书展示页面
2016/07/11 Python
selenium+python实现1688网站验证码图片的截取功能
2018/08/14 Python
详解PyTorch手写数字识别(MNIST数据集)
2019/08/16 Python
python计算导数并绘图的实例
2020/02/29 Python
Pycharm Git 设置方法
2020/09/15 Python
英国高街奥特莱斯:Highstreet Outlet
2019/11/21 全球购物
介绍一下mysql的日期和时间函数
2013/03/28 面试题
护理专业毕业生推荐信
2013/10/31 职场文书
幼师辞职信怎么写
2015/02/27 职场文书
八月一日观后感
2015/06/10 职场文书
教师研修随笔感言
2015/11/18 职场文书
vue中data改变后让视图同步更新的方法
2021/03/29 Vue.js
如何利用python和DOS获取wifi密码
2021/03/31 Python
SpringBoot快速入门详解
2021/07/21 Java/Android
JavaScript高级程序设计之基本引用类型
2021/11/17 Javascript
HTML常用标签超详细整理
2022/03/19 HTML / CSS