编写 TypeScript 并为浏览器和 Node 生成一个库
Write TypeScript and emit a library for Browser and Node
我有一个在 Node.js 和浏览器中使用的内部库。它有许多文件,与 Grunt 任务和不同的序言连接在一起,一个用于浏览器,一个用于 Node:
浏览器:
// dependent 3rd-party libs like Mustache are already global
window.myLib = { /*just a namespace object filled with stuff later*/ }
// then comes the plain javascript which just adds elements to myLib.
// This part is identical to that used in Node
// example:
myLib.renderPartDetail = function (...) {...};
节点:
var Mustache = require('mustache');
var myLib = {};
module.exports = myLib;
// then comes the plain javascript which just adds elements to myLib.
// This part is identical to that used in Browser
这会产生 2 个不同的单一输出 js 文件,一个用于浏览器,一个用于 Node。
我想要什么
- 使用 TypeScript
- 如果可能,对浏览器和节点只使用一种 CommonJS 语法(或 ES6 模块)
- 投资于未来几个月不会消亡的事物
- 更加模块化(也许有人只需要部分库)
我有什么困惑[=63=]
我在 TypeScript 中发现了 2 种不同的模块处理方式:
import {a, b} from './x'
和
import c = require('./y')
我从 node 习惯了后者,但第一个看起来像 ES6(可能是未来)。
目前我使用tsc --module commonjs
但这只是输出格式,对吧?还有 --module system
但我找不到此选项的文档,当我使用它时,编译器抱怨 export = ...
is not allowed.
还没有玩过 browserify
、tsify
、watchify
、jspm
、SystemJS、webpack
- 它太相似了很多,但我认为这些工具中的一个或几个可以为我完成这项工作。
而当我require(<a node module living in node_modules>)
时,tsc找不到模块:"TS2307: Cannot find external module 'moment'".
具体问题
- 我应该在我的代码中使用哪种模块语法才能最好地使用 Node 和浏览器?
- 哪个工具链可以解决我的需求?有没有我可以从中复制的示例项目或样板? (我也对 Gulp 持开放态度,不必使用 Grunt)。
- 目前支持哪些 TypeScript 和 Node 版本?我在 IntelliJ 中嵌入了 1.4,当将 1.6.2 引用为外部时,我收到非常深奥的神秘错误消息,例如 "TypeError: host.fileExists is not a function"(没有发现任何有用的信息)。也许使用 Node v4.1.1 不是最佳选择?
很抱歉 post 太复杂了。如有必要,请给我建议从哪里开始,或者最重要的改变或开始的事情是什么。
Which module syntax should I use in my code to best work with Node and Browser?
如果您的目标是 es5
,那么两种语法都会编译成实际上相同的东西。使用其中任何一种,并随意混合搭配。
Which tool-chain will solve my requirements? Is there an example project or a boilerplate where I can copy from
我使用(并推荐)webpack。你可以按原样使用 commonjs / nodejs,然后 webpack 可以为前端创建包。有关示例,请参阅 https://github.com/basarat/tsb/tree/master
Which TypeScript and Node versions are currently supported? I'm having 1.4 embedded in IntelliJ, when referencing 1.6.2 as external I'm getting very deep cryptic error messages like "TypeError: host.fileExists is not a function" (not finding anything helpful about this). Maybe it's not optimal to use Node v4.1.1?
使用最新的 TypeScript(来自 TypeStrong 的各种工具,例如 atom-typescript/grunt-ts/ts-loader 支持)。您得到的错误是一个 webstorm 错误,应该报告给他们。 (我使用 atom-typescript)。
我还有 TypeError: host.fileExists WebStorm 10 和自定义 Typescript 编译器(通过 npm 安装)的错误。
但是,这 已在 WebStorm 11(2015 年 11 月 2 日发布)中修复
https://www.jetbrains.com/webstorm/download/
这是我使用 webpack 和 babel 得到它的方式:
我的 index.ts
文件在 src
文件夹中
package.json
{
"scripts": {
"bundle-dev" : "rimraf dist && tsc --outDir dist/temp && webpack --env.development --display-error-details && rimraf dist/temp",
"bundle-prod": "rimraf dist && tsc --outDir dist/temp && webpack --env.production --display-error-details && rimraf dist/temp"
},
"devDependencies": {
"@babel/core": "^7.11.6",
"@babel/plugin-transform-reserved-words": "^7.10.4",
"@babel/plugin-transform-typescript": "^7.11.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"@babel/plugin-syntax-flow": "^7.10.4",
"@babel/preset-env": "^7.11.5",
"babel-loader": "^8.1.0",
"esmify": "^2.1.1",
"rimraf": "^3.0.2",
"ts-loader": "^8.0.4",
"ts-node": "^8.10.2",
"typescript": "^3.9.7",
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12"
}
}
tsconfig.json
{
"compilerOptions": {
"module": "AMD",
"target": "ES5",
"declaration": true,
"outDir": "dist/my-javascript-package",
"moduleResolution": "node"
},
"exclude": [
"node_modules"
],
"include": [
"src/**/*"
]
}
.babelrc
{
"plugins": [
"transform-class-properties",
"@babel/plugin-syntax-flow",
"@babel/plugin-transform-reserved-words",
"@babel/plugin-transform-typescript"
]
}
webpack.config.js
const path = require('path');
module.exports = env => {
const mode = env.production ? 'production' : 'development';
const config = (target) => {
return {
entry: {
index: './src/index.ts'
},
target: target,
output: {
path: path.resolve(__dirname, "dist/my-javascript-package"),
filename: target+'.js',
library: 'MyJavaScriptPackage',
libraryTarget: "umd",
umdNamedDefine: true,
globalObject: 'this',
},
plugins: [
new (require('webpack')).DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(mode)
}),
],
mode: mode,
resolve: {
extensions: ['.ts', '.js', '.json']
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
options: {
presets: [
[
"@babel/preset-env",
{
"targets": {
"browsers":["last 2 versions"],
"node":"current"
}
}
]
],
},
},
{
loader: "ts-loader",
},
],
},
],
},
};
};
return [config('node'), config('web')]
};
捆绑它
npm run bundle-dev
或
npm run bundle-prod
导入
import {MyJavaScriptPackage} from "my-javascript-package/node";
//or
import {MyJavaScriptPackage} from "my-javascript-package/web"; // SPA example
参考文献:
我有一个在 Node.js 和浏览器中使用的内部库。它有许多文件,与 Grunt 任务和不同的序言连接在一起,一个用于浏览器,一个用于 Node:
浏览器:
// dependent 3rd-party libs like Mustache are already global
window.myLib = { /*just a namespace object filled with stuff later*/ }
// then comes the plain javascript which just adds elements to myLib.
// This part is identical to that used in Node
// example:
myLib.renderPartDetail = function (...) {...};
节点:
var Mustache = require('mustache');
var myLib = {};
module.exports = myLib;
// then comes the plain javascript which just adds elements to myLib.
// This part is identical to that used in Browser
这会产生 2 个不同的单一输出 js 文件,一个用于浏览器,一个用于 Node。
我想要什么
- 使用 TypeScript
- 如果可能,对浏览器和节点只使用一种 CommonJS 语法(或 ES6 模块)
- 投资于未来几个月不会消亡的事物
- 更加模块化(也许有人只需要部分库)
我有什么困惑[=63=]
我在 TypeScript 中发现了 2 种不同的模块处理方式:
import {a, b} from './x'
和
import c = require('./y')
我从 node 习惯了后者,但第一个看起来像 ES6(可能是未来)。
目前我使用tsc --module commonjs
但这只是输出格式,对吧?还有 --module system
但我找不到此选项的文档,当我使用它时,编译器抱怨 export = ...
is not allowed.
还没有玩过 browserify
、tsify
、watchify
、jspm
、SystemJS、webpack
- 它太相似了很多,但我认为这些工具中的一个或几个可以为我完成这项工作。
而当我require(<a node module living in node_modules>)
时,tsc找不到模块:"TS2307: Cannot find external module 'moment'".
具体问题
- 我应该在我的代码中使用哪种模块语法才能最好地使用 Node 和浏览器?
- 哪个工具链可以解决我的需求?有没有我可以从中复制的示例项目或样板? (我也对 Gulp 持开放态度,不必使用 Grunt)。
- 目前支持哪些 TypeScript 和 Node 版本?我在 IntelliJ 中嵌入了 1.4,当将 1.6.2 引用为外部时,我收到非常深奥的神秘错误消息,例如 "TypeError: host.fileExists is not a function"(没有发现任何有用的信息)。也许使用 Node v4.1.1 不是最佳选择?
很抱歉 post 太复杂了。如有必要,请给我建议从哪里开始,或者最重要的改变或开始的事情是什么。
Which module syntax should I use in my code to best work with Node and Browser?
如果您的目标是 es5
,那么两种语法都会编译成实际上相同的东西。使用其中任何一种,并随意混合搭配。
Which tool-chain will solve my requirements? Is there an example project or a boilerplate where I can copy from
我使用(并推荐)webpack。你可以按原样使用 commonjs / nodejs,然后 webpack 可以为前端创建包。有关示例,请参阅 https://github.com/basarat/tsb/tree/master
Which TypeScript and Node versions are currently supported? I'm having 1.4 embedded in IntelliJ, when referencing 1.6.2 as external I'm getting very deep cryptic error messages like "TypeError: host.fileExists is not a function" (not finding anything helpful about this). Maybe it's not optimal to use Node v4.1.1?
使用最新的 TypeScript(来自 TypeStrong 的各种工具,例如 atom-typescript/grunt-ts/ts-loader 支持)。您得到的错误是一个 webstorm 错误,应该报告给他们。 (我使用 atom-typescript)。
我还有 TypeError: host.fileExists WebStorm 10 和自定义 Typescript 编译器(通过 npm 安装)的错误。
但是,这 已在 WebStorm 11(2015 年 11 月 2 日发布)中修复 https://www.jetbrains.com/webstorm/download/
这是我使用 webpack 和 babel 得到它的方式:
我的 index.ts
文件在 src
文件夹中
package.json
{
"scripts": {
"bundle-dev" : "rimraf dist && tsc --outDir dist/temp && webpack --env.development --display-error-details && rimraf dist/temp",
"bundle-prod": "rimraf dist && tsc --outDir dist/temp && webpack --env.production --display-error-details && rimraf dist/temp"
},
"devDependencies": {
"@babel/core": "^7.11.6",
"@babel/plugin-transform-reserved-words": "^7.10.4",
"@babel/plugin-transform-typescript": "^7.11.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"@babel/plugin-syntax-flow": "^7.10.4",
"@babel/preset-env": "^7.11.5",
"babel-loader": "^8.1.0",
"esmify": "^2.1.1",
"rimraf": "^3.0.2",
"ts-loader": "^8.0.4",
"ts-node": "^8.10.2",
"typescript": "^3.9.7",
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12"
}
}
tsconfig.json
{
"compilerOptions": {
"module": "AMD",
"target": "ES5",
"declaration": true,
"outDir": "dist/my-javascript-package",
"moduleResolution": "node"
},
"exclude": [
"node_modules"
],
"include": [
"src/**/*"
]
}
.babelrc
{
"plugins": [
"transform-class-properties",
"@babel/plugin-syntax-flow",
"@babel/plugin-transform-reserved-words",
"@babel/plugin-transform-typescript"
]
}
webpack.config.js
const path = require('path');
module.exports = env => {
const mode = env.production ? 'production' : 'development';
const config = (target) => {
return {
entry: {
index: './src/index.ts'
},
target: target,
output: {
path: path.resolve(__dirname, "dist/my-javascript-package"),
filename: target+'.js',
library: 'MyJavaScriptPackage',
libraryTarget: "umd",
umdNamedDefine: true,
globalObject: 'this',
},
plugins: [
new (require('webpack')).DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(mode)
}),
],
mode: mode,
resolve: {
extensions: ['.ts', '.js', '.json']
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
options: {
presets: [
[
"@babel/preset-env",
{
"targets": {
"browsers":["last 2 versions"],
"node":"current"
}
}
]
],
},
},
{
loader: "ts-loader",
},
],
},
],
},
};
};
return [config('node'), config('web')]
};
捆绑它
npm run bundle-dev
或
npm run bundle-prod
导入
import {MyJavaScriptPackage} from "my-javascript-package/node";
//or
import {MyJavaScriptPackage} from "my-javascript-package/web"; // SPA example
参考文献: