【问题标题】:Typescript compile to single file打字稿编译为单个文件
【发布时间】:2016-04-01 04:32:08
【问题描述】:

我正在使用 TS 1.7,我正在尝试将我的项目编译成一个大文件,我可以将其包含在我的 html 文件中。

我的项目结构如下:

-build // Build directory
-src // source root
--main.ts // my "Main" file that uses the imports my outer files
--subDirectories with more ts files.
-package.json
-tsconfig.json

我的 tsconfig 文件是:

 {
  "compilerOptions": {
    "module":"amd",
    "target": "ES5",
    "removeComments": true,
    "preserveConstEnums": true,
    "outDir": "./build",
    "outFile":"./build/build.js",
    "sourceRoot": "./src/",
    "rootDir": "./src/",
    "sourceMap": true
  }
}

当我构建我的项目时,我希望 build.js 文件是从我的源代码编译的一个大文件。 但是这个 build.js 文件是空的,我把所有的文件都编译成了 js 文件。

我的每个 TS 文件看起来有点像这样

import {blabla} from "../../bla/blas";

export default class bar implements someThing {
    private variable : string;
}

我做错了什么?

【问题讨论】:

  • 我最喜欢的实现方式是使用 esbuild。它是用 go 编写的,因此比 TSC 快得多,比 webpack 快 100 倍。见esbuild.github.io。它支持 outFile 和 outDir 选项。

标签: javascript typescript


【解决方案1】:

这将在 TypeSript 1.8 中实现。在该版本中,当 moduleamdsystem 时,outFile 选项有效。

目前该功能在 Typescript 的开发版本中可用。 要安装该运行:

$ npm install -g typescript@next

对于以前的版本,即使不明显 moduleoutFile 选项也不能一起使用。

您可以查看this 问题了解更多详情。


如果要输出版本低于 1.8 的单个文件,则不能使用 tsconfig.json 中的 module 选项。相反,您必须使用 module 关键字来创建命名空间。

您的 tsconfig.json 文件应如下所示:

{
  "compilerOptions": {
    "target": "ES5",
    "removeComments": true,
    "preserveConstEnums": true,
    "outFile": "./build/build.js",
    "sourceRoot": "./src/",
    "rootDir": "./src/",
    "sourceMap": true
  }
}

您的 TS 文件也应如下所示:

module SomeModule {
  export class RaceTrack {
    constructor(private host: Element) {
      host.appendChild(document.createElement("canvas"));
    }
  }
}

您必须通过命名空间引用导入,而不是使用 import 语句。

window.addEventListener("load", (ev: Event) => {
  var racetrack = new SomeModule.RaceTrack(document.getElementById("content"));
});

【讨论】:

  • 您指出的问题似乎已解决,github.com/Microsoft/TypeScript/wiki/Compiler-Options 也建议将 --outFile 标志与 --module 标志一起使用。
  • 确实如此,但它似乎不起作用。 :( 也许在 github 上提出一个问题?
  • 顺便说一句,github 上的问题的解决似乎并不指向代码库的任何实际更改,它们总是以默认行为关闭。
  • 我编辑了答案以包含@next 部分,这样更清楚。 :)
  • 有没有更好的方法来使用 TypeScript 3.x?
【解决方案2】:

选项 1 - 如果您不使用模块

如果您的代码仅包含常规 Typescript,没有模块(导入/导出),您只需将参数 outfile 添加到您的 tsconfig.json

// tsconfig.json
{
    "compilerOptions": {
        "lib": ["es5", "es6", "dom"],
        "rootDir": "./src/",
        "outFile": "./build/build.js"
    }
}

但是这个选项有一些限制。

如果您收到此错误:

Cannot compile modules using option 'outFile' unless the '--module' flag is 'amd' or 'system'

试试下面的“选项 2”。

选项 2 - 使用模块加载器

如果您正在使用模块(导入/导出),则需要一个模块加载器来在浏览器中运行已编译的脚本。

当您编译为单个文件(使用 outFile)时,Typescript 原生支持编译为 amdsystem 模块加载器。

在tsconfig中,需要将module设置为amdsystem

// tsconfig.json
{
    "compilerOptions": {
        "module": "AMD",
        "lib": ["es5", "es6", "dom"],
        "rootDir": "./src/",
        "outFile": "./build/build.js"
    }
}

如果选择 AMD,则需要使用 require.js 运行时。 AMD 需要 AMD 加载程序,require.js 是最流行的选项 (https://requirejs.org/)。

如果选择System,则需要使用SystemJS模块加载器(https://github.com/systemjs/systemjs)。

选项 3 - 使用模块捆绑器/构建工具

或许,最好的选择是使用模块捆绑器/构建工具,例如 Webpack。

Webpack 会将你所有的 TypeScript 文件编译成一个 JavaScript 包。

所以,你将使用webpack 来编译,而不是tsc

首先安装 webpack,webpack-clits-loader

npm install --save-dev webpack webpack-cli typescript ts-loader

如果你使用 webpack 和 Typescript,最好使用 modulecommonjs

// tsconfig.json
{
    "compilerOptions": {
        "module": "commonjs",
        "lib": ["es5", "es6", "dom"],
        "rootDir": "src"
    }
}

Webpack webpack.config.js 示例:

//webpack.config.js
const path = require('path');

module.exports = {
  mode: "development",
  devtool: "inline-source-map",
  entry: {
    main: "./src/YourEntryFile.ts",
  },
  output: {
    path: path.resolve(__dirname, './build'),
    filename: "[name]-bundle.js" // <--- Will be compiled to this single file
  },
  resolve: {
    extensions: [".ts", ".tsx", ".js"],
  },
  module: {
    rules: [
      { 
        test: /\.tsx?$/,
        loader: "ts-loader"
      }
    ]
  }
};

现在,要编译,而不是使用tsc 命令执行,使用webpack 命令。

package.json 示例:

{
  "name": "yourProject",
  "version": "0.1.0",
  "private": true,
  "description": "",
  "scripts": {
    "build": "webpack" // <---- compile ts to a single file
  },
  "devDependencies": {
    "ts-loader": "^8.0.2",
    "typescript": "^3.9.7",
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12"
  }
}

Webpack's TypeScript Documentation

最后,编译所有内容(最好在监视模式下):

npx webpack -w

【讨论】:

  • 您的解决方案不起作用。我得到“无法使用选项 'outFile' 编译模块,除非 '--module' 标志是 'amd' 或 'system'。”
  • @AlkisMavridis 对我来说也一样。你找到解决办法了吗?
  • @AlkisMavridis 如果您使用模块,我用其他选项更新了我的答案以编译为单个文件。
  • 别忘了用npm i webpack-cli 安装CLI 并用npx webpack -w 在监视模式下巧妙地运行Webpack。
  • @JohnF 该文件是“package.json”,位于根目录。我更新了答案。 docs.npmjs.com/creating-a-package-json-file
【解决方案3】:

最简单的方法

您可以使用名为ncc 的自定义工具来完成此操作,该工具由Vercel 构建和维护。以下是他们在create-next-app 中的使用方式:

ncc build ./index.ts -w -o dist/

用纱线安装它:

yarn add @vercel/ncc

或 npm:

npm install @vercel/ncc

【讨论】:

  • 这是否会创建可以直接在浏览器中运行的代码?我的浏览器说“__dirname”没有定义
  • 我不知道,但根据您分享的内容,答案似乎是否定的。 __dirname 是特定于 node.js 的环境变量。
  • ncc 适用于 Node.js 项目,例如,如果您想构建从 TypeScript 到 JavaScript 的数据库种子脚本。这些脚本通常是用 JavaScript “手工”编写的,而使用 ncc,您可以为您的应用重用您用 TypeScript 编写的代码。
  • @rambi 你可以通过一个小技巧在浏览器中运行它。在您的 HTML 文件中,在 ncc 的输出之前的某处添加 var __dirname = "", module = {}。在单独的脚本标签中执行此操作可能是最简单的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-30
  • 1970-01-01
  • 2017-06-04
相关资源
最近更新 更多