如何在客户端使用外部打字稿库?
How to use external typescript libraries on client side?
我已遵循此指南:How to compile Typescript into a single file with amd modules with gulp。
App.ts
import { CreateModel } from "./Models/CreateModel";
import { CreateView } from "./Views/CreateView";
import { CreateController } from "./Controllers/CreateController";
export class App {
public init() {
const model = new CreateModel();
const view = new CreateView(model);
const controller = new CreateController(model, view);
}
}
CreateController.ts
export class CreateController {
private model: CreateModel;
private view: CreateView;
constructor(model: CreateModel, view: CreateView) {
this.model = model;
this.view = view;
this.init();
}
more code...
}
CreateView.ts
import { CreateModel } from "../Models/CreateModel";
export class CreateView {
private model: CreateModel;
constructor(model: CreateModel) {
this.model = model;
this.init();
}
more code...
}
CreateModel.ts
export class CreateModel {
more code...
}
index.html
<script src="~/Scripts/config.js"></script>
<script data-main="main" src="~/Scripts/require.js"></script>
config.js
var require = {
baseUrl: "../../Scripts/",
paths: {
'App': 'app'
}
};
main.js
requirejs(['App'], function (MyApp) {
var app = new MyApp.App();
app.init();
});
tsconfig.json
{
"compileOnSave": true,
"compilerOptions": {
"lib": [ "es2017", "dom" ],
"moduleResolution": "node",
"module": "amd",
"noImplicitAny": true,
"noEmitOnError": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"outFile": "./Scripts/app.js",
"removeComments": false,
"sourceMap": true,
"target": "es5"
},
"files": [
"Scripts/Typescripts/App.ts"
],
"exclude": [
"node_modules"
],
"include": [
"./Scripts/Typescripts/**/*"
]
}
这工作正常,一切都编译成 ~/Scripts/app.js。现在我想为此添加一个外部库。它是 ts.validator.fluent 并且在 npm 上。我如何在客户端使用它?
我尝试从 Github 下载文件,将其放在单独的文件夹中,然后导入:
CreateController.ts
import { IValidator, Validator, ValidationResult } from './Plugins/ts.validator.fluent';
export class CreateController {
...
private checkEmail(validateVm: ValidateVm) {
let validationResult = new Validator(validateVm.value).Validate(ValidateRules.email);
...
}
}
但是当我 运行 这样做时,我得到以下错误:
Failed to load resource: the server responded with a status of 404 (Not Found)
Uncaught Error: Script error for "Plugins/ts.validator.fluent", needed by: Controllers/CreateController
最好的方法是什么?
在客户端代码中使用 npm 依赖项的最佳方式可能是使用 webpack.
Webpack 可以获取您的 JS 文件,解析导入,然后创建一个包,其中包含您依赖的所有代码(类似于您创建单个 app.js
JavaScript 文件。当 webpack 看到解析为 npm 模块的导入时,它也会自动包含该代码。
注意:您需要注意只使用设计用于客户端的 NPM 包,不要依赖于 Node.js 环境。许多包被设计为仅在服务器端使用,并依赖于节点库等...
此时使用 require 可能变得不必要,并使事情变得更复杂,因为 webpack 的自动捆绑会做类似的事情,此外,将所有代码导出为单个 typescript 文件可能会使事情复杂化。
我会推荐以下构建过程:
- 编译所有打字稿代码,并导出到临时目录(例如
.tmp
)
- 使用webpack处理
.tmp
中的.js
个文件,指定main
入口点。
对于这样的事情,开始使用像 gulp 这样的构建系统可能是个好主意,而不是使用 运行 构建项目所需的单独命令。您还可以使用 package.json
中的 "scripts"
属性 来编写构建命令,这样您就不会发现自己必须手动 运行 许多不同的命令。
我最终遵循了 Sam Lanning 的回答,现在它起作用了!
文件夹结构
├── Scripts
| ├── Ts-build
| ├── Typescripts
| ├── Subfolders
| App.ts
| App.js
└── index.html
tsconfig.json
webpack.config.js
package.json
{
"name": "MyProject",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"ts.validator.fluent": "^1.3.0"
},
"devDependencies": {
"@types/bootstrap": "^4.3.1",
"@types/jquery": "^3.3.30",
"@types/node": "^12.6.9",
"jquery": "^3.4.1",
"lodash": "^4.17.15",
"popper.js": "^1.15.0",
"source-map-loader": "^0.2.4",
"typescript": "^3.5.3",
"webpack": "^4.39.0",
"webpack-cli": "^3.3.6"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"author": "",
"license": "ISC"
}
webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
devtool: 'source-map',
entry: './Scripts/Ts-build/App',
mode: 'development',
target: 'web',
watch: true,
output: {
filename: 'app.js',
path: path.resolve(__dirname, './Scripts')
},
module: {
rules: [{
test: /\.(js)?$/,
include: path.resolve(__dirname, './Scripts/Ts-build/'),
exclude: /node_modules/
},
{
enforce: "pre",
test: /\.js$/,
loader: "source-map-loader"
}]
},
resolve: {
extensions: [".webpack.js", ".web.js", ".js"]
},
externals: {
// require("jquery") is external and available
// on the global var jQuery
"jquery": "jQuery"
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
})
]
};
我已遵循此指南:How to compile Typescript into a single file with amd modules with gulp。
App.ts
import { CreateModel } from "./Models/CreateModel";
import { CreateView } from "./Views/CreateView";
import { CreateController } from "./Controllers/CreateController";
export class App {
public init() {
const model = new CreateModel();
const view = new CreateView(model);
const controller = new CreateController(model, view);
}
}
CreateController.ts
export class CreateController {
private model: CreateModel;
private view: CreateView;
constructor(model: CreateModel, view: CreateView) {
this.model = model;
this.view = view;
this.init();
}
more code...
}
CreateView.ts
import { CreateModel } from "../Models/CreateModel";
export class CreateView {
private model: CreateModel;
constructor(model: CreateModel) {
this.model = model;
this.init();
}
more code...
}
CreateModel.ts
export class CreateModel {
more code...
}
index.html
<script src="~/Scripts/config.js"></script>
<script data-main="main" src="~/Scripts/require.js"></script>
config.js
var require = {
baseUrl: "../../Scripts/",
paths: {
'App': 'app'
}
};
main.js
requirejs(['App'], function (MyApp) {
var app = new MyApp.App();
app.init();
});
tsconfig.json
{
"compileOnSave": true,
"compilerOptions": {
"lib": [ "es2017", "dom" ],
"moduleResolution": "node",
"module": "amd",
"noImplicitAny": true,
"noEmitOnError": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"outFile": "./Scripts/app.js",
"removeComments": false,
"sourceMap": true,
"target": "es5"
},
"files": [
"Scripts/Typescripts/App.ts"
],
"exclude": [
"node_modules"
],
"include": [
"./Scripts/Typescripts/**/*"
]
}
这工作正常,一切都编译成 ~/Scripts/app.js。现在我想为此添加一个外部库。它是 ts.validator.fluent 并且在 npm 上。我如何在客户端使用它?
我尝试从 Github 下载文件,将其放在单独的文件夹中,然后导入:
CreateController.ts
import { IValidator, Validator, ValidationResult } from './Plugins/ts.validator.fluent';
export class CreateController {
...
private checkEmail(validateVm: ValidateVm) {
let validationResult = new Validator(validateVm.value).Validate(ValidateRules.email);
...
}
}
但是当我 运行 这样做时,我得到以下错误:
Failed to load resource: the server responded with a status of 404 (Not Found)
Uncaught Error: Script error for "Plugins/ts.validator.fluent", needed by: Controllers/CreateController
最好的方法是什么?
在客户端代码中使用 npm 依赖项的最佳方式可能是使用 webpack.
Webpack 可以获取您的 JS 文件,解析导入,然后创建一个包,其中包含您依赖的所有代码(类似于您创建单个 app.js
JavaScript 文件。当 webpack 看到解析为 npm 模块的导入时,它也会自动包含该代码。
注意:您需要注意只使用设计用于客户端的 NPM 包,不要依赖于 Node.js 环境。许多包被设计为仅在服务器端使用,并依赖于节点库等...
此时使用 require 可能变得不必要,并使事情变得更复杂,因为 webpack 的自动捆绑会做类似的事情,此外,将所有代码导出为单个 typescript 文件可能会使事情复杂化。
我会推荐以下构建过程:
- 编译所有打字稿代码,并导出到临时目录(例如
.tmp
) - 使用webpack处理
.tmp
中的.js
个文件,指定main
入口点。
对于这样的事情,开始使用像 gulp 这样的构建系统可能是个好主意,而不是使用 运行 构建项目所需的单独命令。您还可以使用 package.json
中的 "scripts"
属性 来编写构建命令,这样您就不会发现自己必须手动 运行 许多不同的命令。
我最终遵循了 Sam Lanning 的回答,现在它起作用了!
文件夹结构
├── Scripts
| ├── Ts-build
| ├── Typescripts
| ├── Subfolders
| App.ts
| App.js
└── index.html
tsconfig.json
webpack.config.js
package.json
{
"name": "MyProject",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"ts.validator.fluent": "^1.3.0"
},
"devDependencies": {
"@types/bootstrap": "^4.3.1",
"@types/jquery": "^3.3.30",
"@types/node": "^12.6.9",
"jquery": "^3.4.1",
"lodash": "^4.17.15",
"popper.js": "^1.15.0",
"source-map-loader": "^0.2.4",
"typescript": "^3.5.3",
"webpack": "^4.39.0",
"webpack-cli": "^3.3.6"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"author": "",
"license": "ISC"
}
webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
devtool: 'source-map',
entry: './Scripts/Ts-build/App',
mode: 'development',
target: 'web',
watch: true,
output: {
filename: 'app.js',
path: path.resolve(__dirname, './Scripts')
},
module: {
rules: [{
test: /\.(js)?$/,
include: path.resolve(__dirname, './Scripts/Ts-build/'),
exclude: /node_modules/
},
{
enforce: "pre",
test: /\.js$/,
loader: "source-map-loader"
}]
},
resolve: {
extensions: [".webpack.js", ".web.js", ".js"]
},
externals: {
// require("jquery") is external and available
// on the global var jQuery
"jquery": "jQuery"
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
})
]
};