WebPack with TypeScript is a bit tricky to get working properly. There are two immediate issues that need to be solved fist:
- In addition to TypeScript imports, WebPack needs extra
require
statements for every import to build the dependency tree for bundling. Otherwise, a module won't be packaged if the export is not used directly; for example if you only used a type reference during compile time (stackoverflow.com: Webpack with typescript external commonjs module) - TypeScript won't understand
require
statements that are needed for webpack to build the dependency tree for bundling (stackoverflow.com: typescript getting error TS2304: cannot find name 'require')
This example project is a proof of concept that solves this problem using the preprocessor loader, so that you don't have to change your code at all to make this work properly.
npm install
npm install -g webpack
webpack
Then open index.html
and check that both ClassA and ClassB are packaged properly (they log a message in the browser console and are included in the bundle.js).
Verify that the .ts
sources don't include the workaround scripts.
These imports exist in the code entry.ts
:
import ClassA = require('ClassA');
import ClassB = require('ClassB');
First, this is not enough for WebPack to understand it needs to always bundle ClassA.ts
and ClassB.ts
, even if the exports are not directly used, but only referenced. To fix this, we need to add extra WebPack-only imports:
require('ClassA');
import ClassA = require('ClassA');
require('ClassB');
import ClassB = require('ClassB');
second, TypeScript will throw an error because it doesn't recognize require
statements.
ERROR in /home/ubuntu/workspace/project/src/entry.ts
(3,15): error TS2304: Cannot find name 'require'.
To fix this, we need to declare require
on top
declare var require: any;
require('ClassA');
import ClassA = require('ClassA');
require('ClassB');
import ClassB = require('ClassB');
Now everything will work.
These steps are automated in this example project: using the preprocessor, it prepends every .ts
source with a require
shim and it modifies every line that contains an import using a regular expression.
// webpack.config.js
module: {
loaders: [{
test: /\.tsx?$/,
loader: 'ts-loader!preprocessor?file&config=preprocess-ts.json'
}]
}
// preprocess-ts.json
{
"line": true,
"file": false,
"callbacks": [{
"fileName": "all",
"scope": "source",
"callback": "(function fixTs(source, fileName) { return 'declare var require: any;' + source; })"
}, {
"fileName": "all",
"scope": "line",
"callback": "(function fixTs(line, fileName, lineNumber) { return line.replace(/^(import.*(require\\(.*?\\)))/g, '$2;$1'); })"
}]
}
The regular expression to add require statements is very rudimentary (crude). The current version only works for the demo project where statements are import something = require('module');
:
return line.replace(/^(import.*(require\\(.*?\\)))/g, '$2;$1');
// import ClassA = require('ClassA');
// becomes:
// require('ClassA'); import ClassA = require('ClassA');
One more thing, notice all .ts files have an empty line at the end. This is needed due to a pending bug in the preprocessor loader.