经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » webpack » 查看文章
浅谈TypeScript 用 Webpack/ts-node 运行的配置记录
来源:jb51  时间:2019/10/12 9:02:23  对本文有异议

公司项目代码是用 TypeScript 写的, 中间遇到有些代码不要放到 Node 里面去跑.

具体场景一些路由配置, 比较大的一块 JSON 数据定义在 TypeScript 里.

我另外有增加脚本, 基于这些 JSON 数据用来生成切换路由的函数.

这就需要运行 TypeScript 了, 而且可能包含一些额外的业务代码.

首先 Node 运行 TypeScript 有提供 ts-node 用来处理.

ts-node 会先编译 TypeScript 代码到 JavaScript, 再调用 Node 运行.

不过这个办法有一些问题, 一个是 TypeScript 定义的路径配置不成功,

另一个问题更麻烦点, 就是引用到的其他的浏览器端代码因为触发运行而引起报错.

Webpack 打包 TypeScript Node 代码

我先想到了一个相对省事的方案, 就是用 Webpack 对 TypeScript 进行打包.

打包完成以后输出 JavaScript 代码. 而浏览器代码打包进去, 但不一定运行.

由于 TypeScript 配置在 Webpack 当中引用有比较成熟的方案, 整个配置也写好:

  1. module.exports = {
  2. mode: "development",
  3. target: "node",
  4. entry: ["./example/gen-router.ts"],
  5. output: {
  6. filename: "gen-router.js",
  7. path: path.join(__dirname, "../", distFolder),
  8. },
  9. devtool: "none",
  10. module: {
  11. rules: [
  12. // 正常的 TypeScript 编译方式, 我这份是拷贝的.
  13. {
  14. test: /\.tsx?$/,
  15. exclude: [/node_modules/, path.join(__dirname, "scripts")],
  16. use: [
  17. { loader: "cache-loader" },
  18. {
  19. loader: "thread-loader",
  20. options: {
  21. workers: require("os").cpus().length - 1,
  22. },
  23. },
  24. {
  25. loader: "ts-loader",
  26. options: {
  27. happyPackMode: true,
  28. transpileOnly: true,
  29. },
  30. },
  31. ],
  32. },
  33. ],
  34. },
  35. // Node 模块, 写在 external 里面表明不需要进行打包. 注意 commonjs 前缀
  36. externals: {
  37. prettier: "commonjs prettier",
  38. "@jimengio/router-code-generator": "commonjs @jimengio/router-code-generator",
  39. fs: "commonjs fs",
  40. path: "commonjs path",
  41. },
  42. resolve: {
  43. extensions: [".tsx", ".ts", ".js"],
  44. modules: [path.join(__dirname, "example"), "node_modules"],
  45.  
  46. // 引用 Plugin 用于读取 tsconfig.json 文件的配置
  47. plugins: [new TsconfigPathsPlugin({ configFile: path.join(__dirname, "../tsconfig.json") })],
  48. },
  49. };
  50.  

基于这个配置打包以后, TypeScript 的代码被打包好, 并且引用响应的 Node 模块.

运行就满足需求了.

这个方式对于其他的服务端渲染的 TypeScript 代码打包也是类似的.

一些特殊的依赖如果不好处理, 可以放在 Webpack 当中进行打包和映射, 得到 js.

ts-node 运行

Webpack 配置相对直接运行 TypeScript 来说会复杂一点, 所以还是 ts-node 简单.

在依赖少的项目当中, 我改成了用 ts-node 来进行编译运行. 配置如下

  1. {
  2. "compilerOptions": {
  3. "allowSyntheticDefaultImports": true,
  4. "experimentalDecorators": true,
  5. "sourceMap": true,
  6. "noImplicitAny": false,
  7. "noImplicitThis": true,
  8. "strictNullChecks": false,
  9. "moduleResolution": "node",
  10.  
  11. // Node 当前还没有支持直接运行 import/export 语法, 需要编译到 CommonJS
  12. "module": "commonjs",
  13.  
  14. "target": "es2016",
  15. "jsx": "react",
  16. "lib": ["es2016"],
  17. "types": ["node"],
  18. "baseUrl": "./example/",
  19. "paths": {
  20. "models": ["./example/models"]
  21. },
  22. "plugins": []
  23. }
  24. }
  25.  

其实主要修改就 commonjs 那一行, 然后就是加上参数运行

  1. 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 属性是多余的. 所以引用的写法要做调整.

  1. import * as fs from "fs";
  2. import * as path from "path";
  3. import * as prettier from "prettier";

这个可能跟 tsconfig.json 里其他的配置有关联, 我没继续深挖.

整体的代码参考 https://github.com/jimengio/meson-form/pull/62/files

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号