如果不直接使用,WebPack 包中不包含导出的 TypeScript 类 [英] Exported TypeScript Class not included in WebPack bundle if not used directly
问题描述
我正在将一个带有 Angular 1.x 的 javascript 项目转换为 WebPack 和 TypeScript(使用 ts-loader).我大部分时间都在工作,但是当 ts-loader 似乎在没有直接使用导出的情况下优化我的脚本时,我遇到了麻烦.
I'm converting a javascript project with Angular 1.x to WebPack and TypeScript (using ts-loader). I got it mostly working, but I'm running into trouble when ts-loader seems to be optimizing my scripts out of the bundle when the exports are not directly used.
这是一个演示问题的示例项目(npm install、webpack,然后加载 index.html 并观察控制台).
Here's a sample project demonstrating the issue (npm install, webpack, then load index.html and watch the console).
https://github.com/bbottema/webpack-typescript
来自 ClassA 的日志记录显示,但 angular 报告 ClassB 丢失(提供程序).如果您查看 bundle.js,您会发现 ClassB 完全丢失了.不同的是ClassA导入后直接开始使用,ClassB只被类型引用编译.
The logging from ClassA is showing up, but angular is reporting ClassB missing (provider). If you look in bundle.js you'll notice ClassB missing entirely. The difference is ClassA begin use directly after importing, and ClassB is only referenced by type for compilation.
这是一个错误,还是有办法强制包含 ClassB?还是我做错了?Angular 2 可能会解决这个问题,但现在这一步太大了.
Is it a bug, or is there a way to force ClassB to be included? Or am I going about it wrong? Angular 2 would probably solve this issue, but that's a step too large right now.
上述项目的相关脚本:
package.json
package.json
{
"devDependencies": {
"typescript": "^1.7.5",
"ts-loader": "^0.8.1"
},
"dependencies": {
"angular": "1.4.9"
}
}
webpack.config.js
webpack.config.js
var path = require('path');
module.exports = {
entry: {
app: './src/entry.ts'
},
output: {
filename: './dist/bundle.js'
},
resolve: {
root: [
path.resolve('./src/my_modules'),
path.resolve('node_modules')
],
extensions: ['', '.ts', '.js']
},
module: {
loaders: [{
test: /\.tsx?$/,
loader: 'ts-loader'
}]
}
};
tsconfig.json
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs"
},
"exclude": [
"node_modules"
]
}
index.html
<!doctype html>
<html ng-app="myApp">
<body>
<script src="dist/bundle.js"></script>
</body>
</html>
入口.js
declare var require: any;
'use strict';
import ClassA = require('ClassA');
import ClassB = require('ClassB');
var a:ClassA = new ClassA(); // direct use, this works
var angular = require('angular');
angular.module('myApp', []).
// this compiles as it should, but in runtime the provider will not be packaged and angular will throw an error
run(function(myProvider: ClassB) {
}
);
ClassA.ts
// this line will be logged just fine
console.log('ClassA.ts: if you see this, then ClassA.ts was packaged properly');
class ClassA {
}
export = ClassA;
ClassB.ts
declare var require: any;
// this line is never logged
console.log('ClassB.ts: if you see this, then ClassB.ts was packaged properly');
class ClassB {
}
var angular = require(angular);
angular.module('myApp').service(new ClassB());
export = ClassB;
推荐答案
原来是你必须通过在没有 import
语句的情况下添加额外的 require
调用来通知 WebPack 显式包含一个模块.
Turns out you have to signal WebPack to explicitly include a module by adding an extra require
call without import
statement.
我还没有准备好通过添加重复导入来破坏我的 .ts 文件,所以我使用 预处理器加载器:
I'm not ready to mangle my .ts files by adding duplicate imports, so I made a generic solution for that using the preprocessor loader:
{
"line": false,
"file": true,
"callbacks": {
"fileName": "all",
"scope": "line",
"callback": "(function fixTs(line, fileName, lineNumber) { return line.replace(/^(import.*(require\\(.*?\\)))/g, '$2;$1'); })"
}]
}
作为概念证明,此正则表达式版本非常有限,仅支持以下格式:
As a proof of concept, this regex version is very limited it only support the following format:
import ClassA = require('ClassA');
// becomes
require('ClassA');import ClassA = require('ClassA');
但它对我有用.同样,我添加了需要垫片:
But it works for me. Similarly, I'm adding the require shim:
{
"fileName": "all",
"scope": "source",
"callback": "(function fixTs(source, fileName) { return 'declare var require: any;' + source; })"
}
我用这个解决方案制作了一个示例项目.
I made a sample project with this solution.
这篇关于如果不直接使用,WebPack 包中不包含导出的 TypeScript 类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!