Skip to content

Commit

Permalink
Fixes #336. Add happypack compatibility mode (#547)
Browse files Browse the repository at this point in the history
* Fixes #336. Add happypack compatibility mode
* Update README.md
* Made happypack a devDependency - In the longer term move this into test itself. Need to rejig test framework a little first.
* Don't call registerWebpackErrors in happyPackMode
  • Loading branch information
Artem Kozlov authored and johnnyreilly committed May 21, 2017
1 parent 19c7a6f commit 70f0595
Show file tree
Hide file tree
Showing 16 changed files with 158 additions and 13 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -12,4 +12,5 @@ npm-debug.log
!/test/**/expectedOutput-*/**
/**/node_modules
/**/dist
/**/.happypack
!build.js
4 changes: 4 additions & 0 deletions README.md
Expand Up @@ -215,6 +215,10 @@ Advanced option to force files to go through different instances of the
TypeScript compiler. Can be used to force segregation between different parts
of your code.

##### happyPackMode *(boolean) (default=false)*

Enables [`happypack`](https://github.com/amireh/happypack) compatibility mode. This implicitly sets `*transpileOnly*` to `true`. **WARNING!** Some errors will be silently ignored in `happypack` mode (`tsconfig.json` parsing errors, dependency resolution errors, etc.).

#### entryFileIsJs *(boolean) (default=false)*

To be used in concert with the `allowJs` compiler option. If your entry file is JS then you'll need to set this option to true. Please note that this is rather unusual and will generally not be necessary when using `allowJs`.
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -48,6 +48,7 @@
"escape-string-regexp": "^1.0.3",
"fs-extra": "^3.0.0",
"glob": "^7.1.1",
"happypack": "^3.1.0",
"html-webpack-plugin": "^2.17.0",
"jasmine-core": "^2.5.2",
"karma": "^1.3.0",
Expand Down
26 changes: 18 additions & 8 deletions src/index.ts
Expand Up @@ -43,10 +43,13 @@ function loader(this: interfaces.Webpack, contents: string) {

const { sourceMap, output } = makeSourceMap(sourceMapText, outputText, filePath, contents, this);

// Make sure webpack is aware that even though the emitted JavaScript may be the same as
// a previously cached version the TypeScript may be different and therefore should be
// treated as new
this._module.meta.tsLoaderFileVersion = fileVersion;
// _module.meta is not available inside happypack
if (!options.happyPackMode) {
// Make sure webpack is aware that even though the emitted JavaScript may be the same as
// a previously cached version the TypeScript may be different and therefore should be
// treated as new
this._module.meta.tsLoaderFileVersion = fileVersion;
}

callback(null, output, sourceMap);
}
Expand Down Expand Up @@ -82,12 +85,16 @@ function getLoaderOptions(loader: interfaces.Webpack) {
compilerOptions: {},
appendTsSuffixTo: [],
entryFileIsJs: false,
happyPackMode: false,
}, configFileOptions, queryOptions);

options.ignoreDiagnostics = utils.arrify(options.ignoreDiagnostics).map(Number);
options.logLevel = options.logLevel.toUpperCase();
options.instance = instanceName;

// happypack can be used only together with transpileOnly mode
options.transpileOnly = options.happyPackMode ? true : options.transpileOnly;

loaderOptionsCache[instanceName] = options;

return options;
Expand Down Expand Up @@ -182,10 +189,13 @@ function getTranspilationEmit(
fileName,
});

utils.registerWebpackErrors(
loader._module.errors,
utils.formatErrors(diagnostics, instance.loaderOptions, instance.compiler, { module: loader._module })
);
// _module.errors is not available inside happypack - see https://github.com/TypeStrong/ts-loader/issues/336
if (!instance.loaderOptions.happyPackMode) {
utils.registerWebpackErrors(
loader._module.errors,
utils.formatErrors(diagnostics, instance.loaderOptions, instance.compiler, { module: loader._module })
);
}

return { outputText, sourceMapText };
}
Expand Down
13 changes: 8 additions & 5 deletions src/instances.ts
Expand Up @@ -47,7 +47,7 @@ export function getTypeScriptInstance(

const configParseResult = config.getConfigParseResult(compiler, configFile, configFilePath);

if (configParseResult.errors.length) {
if (configParseResult.errors.length && !loaderOptions.happyPackMode) {
utils.registerWebpackErrors(
loader._module.errors,
utils.formatErrors(configParseResult.errors, loaderOptions, compiler, { file: configFilePath }));
Expand All @@ -64,10 +64,13 @@ export function getTypeScriptInstance(
const program = compiler.createProgram([], compilerOptions);
const diagnostics = program.getOptionsDiagnostics();

utils.registerWebpackErrors(
loader._module.errors,
utils.formatErrors(diagnostics, loaderOptions, compiler, {file: configFilePath || 'tsconfig.json'}));

// happypack does not have _module.errors - see https://github.com/TypeStrong/ts-loader/issues/336
if (!loaderOptions.happyPackMode) {
utils.registerWebpackErrors(
loader._module.errors,
utils.formatErrors(diagnostics, loaderOptions, compiler, {file: configFilePath || 'tsconfig.json'}));
}

return { instance: instances[loaderOptions.instance] = { compiler, compilerOptions, loaderOptions, files, dependencyGraph: {}, reverseDependencyGraph: {} }};
}

Expand Down
1 change: 1 addition & 0 deletions src/interfaces.ts
Expand Up @@ -254,6 +254,7 @@ export interface LoaderOptions {
compilerOptions: typescript.CompilerOptions;
appendTsSuffixTo: RegExp[];
entryFileIsJs: boolean;
happyPackMode: boolean;
}

export interface TSFile {
Expand Down
53 changes: 53 additions & 0 deletions test/execution-tests/basic-happypack/karma.conf.js
@@ -0,0 +1,53 @@
/* eslint-disable no-var, strict */
'use strict';
var path = require('path');
var webpack = require('webpack');
var webpackConfig = require('./webpack.config.js');

module.exports = function(config) {
config.set({
browsers: [ 'PhantomJS' ],

files: [
// This loads all the tests
'main.js'
],

port: 9876,

frameworks: [ 'jasmine' ],

logLevel: config.LOG_INFO, //config.LOG_DEBUG

preprocessors: {
'main.js': [ 'webpack', 'sourcemap' ]
},

webpack: {
devtool: 'inline-source-map',
module: webpackConfig.module,
resolve: webpackConfig.resolve,
plugins: webpackConfig.plugins,

// for test harness purposes only, you would not need this in a normal project
resolveLoader: webpackConfig.resolveLoader
},

webpackMiddleware: {
quiet: true,
stats: {
colors: true
}
},

// reporter options
mochaReporter: {
colors: {
success: 'bgGreen',
info: 'cyan',
warning: 'bgBlue',
error: 'bgRed'
}
}
});
};
7 changes: 7 additions & 0 deletions test/execution-tests/basic-happypack/lib/externalLib.d.ts
@@ -0,0 +1,7 @@
declare module externalLib {
export function doSomething(arg: any): void;
}

declare module 'externalLib' {
export = externalLib
}
3 changes: 3 additions & 0 deletions test/execution-tests/basic-happypack/lib/externalLib.js
@@ -0,0 +1,3 @@
module.exports = {
doSomething: function() { }
}
2 changes: 2 additions & 0 deletions test/execution-tests/basic-happypack/main.js
@@ -0,0 +1,2 @@
const testsContext = require.context('./', true, /\.tests\.ts(x?)$/);
testsContext.keys().forEach(testsContext);
3 changes: 3 additions & 0 deletions test/execution-tests/basic-happypack/src/app.ts
@@ -0,0 +1,3 @@
import submodule = require('./submodule/submodule');
import externalLib = require('externalLib');
externalLib.doSomething(submodule);
@@ -0,0 +1,5 @@
import externalLib = require('externalLib');

externalLib.doSomething("");
var message = "Hello from submodule"
export = message
12 changes: 12 additions & 0 deletions test/execution-tests/basic-happypack/test/app.tests.ts
@@ -0,0 +1,12 @@
import submodule = require('../src/submodule/submodule');
import externalLib = require('externalLib');

describe("app", () => {
it("externalLib can be called", () => {
expect(externalLib.doSomething(submodule)).toBeUndefined();
});

it("submodule return value can be reached", () => {
expect(submodule).toBe("Hello from submodule");
});
});
5 changes: 5 additions & 0 deletions test/execution-tests/basic-happypack/tsconfig.json
@@ -0,0 +1,5 @@
{
"compilerOptions": {

}
}
7 changes: 7 additions & 0 deletions test/execution-tests/basic-happypack/typings.json
@@ -0,0 +1,7 @@
{
"name": "simple",
"version": false,
"globalDependencies": {
"jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#fe563dff3428bac1260d1794e2c2ecf8f097535a"
}
}
28 changes: 28 additions & 0 deletions test/execution-tests/basic-happypack/webpack.config.js
@@ -0,0 +1,28 @@
var path = require('path');
var HappyPack = require('happypack');

module.exports = {
entry: './src/app.ts',
output: {
filename: 'bundle.js'
},
resolve: {
alias: { externalLib: path.join(__dirname, "./lib/externalLib.js") },
extensions: ['.ts', '.js']
},
module: {
rules: [
{ test: /\.ts$/, loader: 'happypack/loader?id=ts'}
]
},
plugins: [
new HappyPack({
id: 'ts',
threads : 2,
loaders: [ "ts-loader?" + JSON.stringify({happyPackMode: true}) ]
})
]
};

// for test harness purposes only, you would not need this in a normal project
module.exports.resolveLoader = { alias: { 'ts-loader': require('path').join(__dirname, "../../../index.js") } }

0 comments on commit 70f0595

Please sign in to comment.