浅谈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字典探测用户名工具
Oct 05 Javascript
有关于JS辅助函数inherit()的问题
Apr 07 Javascript
jquery 多行文本框(textarea)高度变化
Jul 03 Javascript
如何判断鼠标是否在DIV的区域内
Nov 13 Javascript
jQuery的ready方法详解
Nov 27 Javascript
node.js中的http.response.end方法使用说明
Dec 14 Javascript
JavaScript 基础函数_深入剖析变量和作用域
May 18 Javascript
JS判断iframe是否加载完成的方法
Aug 03 Javascript
浅谈JavaScript中的this指针和引用知识
Aug 05 Javascript
详解webpack编译多页面vue项目的配置问题
Dec 11 Javascript
基于Axios 常用的请求方法别名(详解)
Mar 13 Javascript
基于vue.js中关于下拉框的值默认及绑定问题
Aug 22 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基础知识:类与对象(3) 构造函数和析构函数
2006/12/13 PHP
php检测网页是否被百度收录的函数代码
2013/10/09 PHP
codeigniter框架批量插入数据
2014/01/09 PHP
Symfony2使用第三方库Upload制作图片上传实例详解
2016/02/04 PHP
PHP+MySQL实现的简单投票系统实例
2016/02/24 PHP
可实现多表单提交的javascript函数
2007/08/01 Javascript
锋利的jQuery 要点归纳(一) jQuery选择器
2010/03/21 Javascript
读jQuery之一(对象的组成)
2011/06/11 Javascript
基于jQuery中对数组进行操作的方法
2013/04/16 Javascript
分享2个jQuery插件--jquery.fileupload与artdialog
2014/12/26 Javascript
使用JavaScript刷新网页的方法
2015/06/04 Javascript
JavaScript实现的背景自动变色代码
2015/10/17 Javascript
自定义类似于jQuery UI Selectable 的Vue指令v-selectable
2017/08/23 jQuery
vue学习教程之带你一步步详细解析vue-cli
2017/12/26 Javascript
Vue实现导出excel表格功能
2018/03/30 Javascript
Nodejs实现爬虫抓取数据实例解析
2018/07/05 NodeJs
vue自定义指令的创建和使用方法实例分析
2018/12/04 Javascript
稍微学一下Vue的数据响应式(Vue2及Vue3区别)
2019/11/21 Javascript
jQuery实现王者荣耀手风琴效果
2020/01/17 jQuery
python缩进区别分析
2014/02/15 Python
python实现一次创建多级目录的方法
2015/05/15 Python
Python3解决棋盘覆盖问题的方法示例
2017/12/07 Python
使用pandas对矢量化数据进行替换处理的方法
2018/04/11 Python
Python实现绘制双柱状图并显示数值功能示例
2018/06/23 Python
基于python3实现socket文件传输和校验
2018/07/28 Python
Linux上使用Python统计每天的键盘输入次数
2019/04/17 Python
Python实现随机爬山算法
2021/01/29 Python
使用Html5 Stream开发实时监控系统
2020/06/02 HTML / CSS
营业员实习自我鉴定
2013/12/07 职场文书
企业为何需要商业计划书
2013/12/26 职场文书
岗位聘任书范文
2014/03/29 职场文书
考核工作实施方案
2014/03/30 职场文书
国庆节演讲稿
2014/05/27 职场文书
促销活动总结模板
2014/07/01 职场文书
班主任师德师风自我剖析材料
2014/10/02 职场文书
幼儿园辞职书
2015/02/26 职场文书