Skip to content

Commit 10e75fa

Browse files
authored
Merge pull request #399 from johnnyreilly/master
Introduce meaningful error when importing TypeScript
2 parents 3490ca6 + a963980 commit 10e75fa

40 files changed

+339
-10
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## v1.3.0
4+
5+
- [Introduce meaningful error when importing TypeScript from `node_modules`](https://github.com/TypeStrong/ts-loader/pull/399)
6+
- [Introduce `entryFileIsJs` loader option which allows having an entry file which is js.](https://github.com/TypeStrong/ts-loader/pull/399) resolves #388 and #401 - thanks @Wykks and @pqr.
7+
8+
NB Previously the `entryFileIsJs` option was on by default when `allowJs` was true. Now it has to be specified directly. Strictly speaking this is a breaking change; however given this is a rarely used option which exists for what is arguably an edge case this is being added without moving to 2.0. If this breaks people then we'll never do this again; I'd be surprised if anyone is relying on this though so we're taking a chance. Related tests have been suffixed "-entryFileIsJs" in the test name.
9+
310
## v1.2.2
411

512
- [Re-exported const enums no longer break emit in watch mode](https://github.com/TypeStrong/ts-loader/pull/377) [#376] - thanks @smphhh

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ Advanced option to force files to go through different instances of the
179179
TypeScript compiler. Can be used to force segregation between different parts
180180
of your code.
181181

182+
#### entryFileIsJs *(boolean) (default=false)*
183+
184+
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`.
182185
183186
#### appendTsSuffixTo *(RegExp[]) (default=[])*
184187
A list of regular expressions to be matched against filename. If filename matches one of the regular expressions, a `.ts` suffix will be appended to that filename.

src/index.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,15 @@ function loader(this: interfaces.Webpack, contents: string) {
2727

2828
const file = updateFileInCache(filePath, contents, instance);
2929

30-
let { outputText, sourceMapText } = options.transpileOnly
30+
const { outputText, sourceMapText } = options.transpileOnly
3131
? getTranspilationEmit(filePath, contents, instance, this)
3232
: getEmit(filePath, instance, this);
3333

3434
if (outputText === null || outputText === undefined) {
35-
throw new Error(`Typescript emitted no output for ${filePath}`);
35+
const additionalGuidance = filePath.indexOf('node_modules') !== -1
36+
? "\nYou should not need to recompile .ts files in node_modules.\nPlease contact the package author to advise them to use --declaration --outDir.\nMore https://github.com/Microsoft/TypeScript/issues/12358"
37+
: "";
38+
throw new Error(`Typescript emitted no output for ${filePath}.${additionalGuidance}`);
3639
}
3740

3841
const { sourceMap, output } = makeSourceMap(sourceMapText, outputText, filePath, contents, this);
@@ -60,6 +63,7 @@ function makeOptions(loader: interfaces.Webpack) {
6063
visualStudioErrorFormat: false,
6164
compilerOptions: {},
6265
appendTsSuffixTo: [],
66+
entryFileIsJs: false,
6367
}, configFileOptions, queryOptions);
6468
options.ignoreDiagnostics = arrify(options.ignoreDiagnostics).map(Number);
6569
options.logLevel = options.logLevel.toUpperCase();

src/instances.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export function ensureTypeScriptInstance(
8989
}
9090

9191
// if allowJs is set then we should accept js(x) files
92-
const scriptRegex = configFile.config.compilerOptions.allowJs
92+
const scriptRegex = configFile.config.compilerOptions.allowJs && loaderOptions.entryFileIsJs
9393
? /\.tsx?$|\.jsx?$/i
9494
: /\.tsx?$/i;
9595

src/interfaces.ts

+1
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ export interface LoaderOptions {
155155
visualStudioErrorFormat: boolean;
156156
compilerOptions: typescript.CompilerOptions;
157157
appendTsSuffixTo: RegExp[];
158+
entryFileIsJs: boolean;
158159
}
159160

160161
export interface TSFile {

src/logger.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ interface InternalLoggerFunc {
1414
(whereToLog: any, messages: string[]): void;
1515
}
1616

17-
const doNothingLogger = (...messages: string[]) => {};
17+
const doNothingLogger = (..._messages: string[]) => {};
1818

1919
function makeLoggerFunc(loaderOptions: interfaces.LoaderOptions) {
2020
return loaderOptions.silent
21-
? (whereToLog: any, messages: string[]) => {}
21+
? (_whereToLog: any, _messages: string[]) => {}
2222
: (whereToLog: any, messages: string[]) => console.log.apply(whereToLog, messages);
2323
}
2424

src/tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"noImplicitReturns": true,
55
"noImplicitThis": false,
66
"noUnusedLocals": true,
7-
"noUnusedParameters": false,
7+
"noUnusedParameters": true,
88
"suppressImplicitAnyIndexErrors": true,
99
"strictNullChecks": false,
1010
"module": "commonjs",

test/comparison-tests/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,7 @@ patch0 is applied:
7373
- test/someFeature/patch0/app.ts - *modified file*
7474
- test/someFeature/expectedOutput/patch0/bundle.js - *bundle after applying patch*
7575
- test/someFeature/expectedOutput/patch0/output.txt - *output after applying patch*
76+
77+
## Flaky tests
78+
79+
Some of the tests in the pack are flaky. For the most part the failures they occasionally experience are not significant. If you want a test to be allowed to fail without failing the overall build whilst still seeing the output then place a file with the name `_FLAKY_` in the root of that particular test.
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
Asset Size Chunks Chunk Names
22
bundle.js 1.43 kB 0 [emitted] main
33
chunk {0} bundle.js (main) 38 bytes [rendered]
4-
[0] ./.test/allowJs/src/index.js 38 bytes {0} [built]
4+
[0] ./.test/allowJs-entryFileIsJs/src/index.js 38 bytes {0} [built]
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
Asset Size Chunks Chunk Names
22
bundle.js 1.41 kB 0 [emitted] main
33
chunk {0} bundle.js (main) 24 bytes [rendered]
4-
[0] ./.test/allowJs/src/index.js 24 bytes {0} [built]
4+
[0] ./.test/allowJs-entryFileIsJs/src/index.js 24 bytes {0} [built]
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
Asset Size Chunks Chunk Names
22
bundle.js 1.43 kB 0 [emitted] main
33
chunk {0} bundle.js (main) 38 bytes [rendered]
4-
[0] ./.test/allowJs/src/index.js 38 bytes {0} [built]
4+
[0] ./.test/allowJs-entryFileIsJs/src/index.js 38 bytes {0} [built]
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
Asset Size Chunks Chunk Names
22
bundle.js 1.41 kB 0 [emitted] main
33
chunk {0} bundle.js (main) 24 bytes [rendered]
4-
[0] ./.test/allowJs/src/index.js 24 bytes {0} [built]
4+
[0] ./.test/allowJs-entryFileIsJs/src/index.js 24 bytes {0} [built]

test/comparison-tests/allowJs/webpack.config.js renamed to test/comparison-tests/allowJs-entryFileIsJs/webpack.config.js

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ module.exports = {
1313
loader: 'ts-loader'
1414
}
1515
]
16+
},
17+
ts: {
18+
entryFileIsJs: true
1619
}
1720
}
1821

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import a = require('a');
2+
3+
console.log(a);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/******/ (function(modules) { // webpackBootstrap
2+
/******/ // The module cache
3+
/******/ var installedModules = {};
4+
5+
/******/ // The require function
6+
/******/ function __webpack_require__(moduleId) {
7+
8+
/******/ // Check if module is in cache
9+
/******/ if(installedModules[moduleId])
10+
/******/ return installedModules[moduleId].exports;
11+
12+
/******/ // Create a new module (and put it into the cache)
13+
/******/ var module = installedModules[moduleId] = {
14+
/******/ exports: {},
15+
/******/ id: moduleId,
16+
/******/ loaded: false
17+
/******/ };
18+
19+
/******/ // Execute the module function
20+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21+
22+
/******/ // Flag the module as loaded
23+
/******/ module.loaded = true;
24+
25+
/******/ // Return the exports of the module
26+
/******/ return module.exports;
27+
/******/ }
28+
29+
30+
/******/ // expose the modules object (__webpack_modules__)
31+
/******/ __webpack_require__.m = modules;
32+
33+
/******/ // expose the module cache
34+
/******/ __webpack_require__.c = installedModules;
35+
36+
/******/ // __webpack_public_path__
37+
/******/ __webpack_require__.p = "";
38+
39+
/******/ // Load entry module and return exports
40+
/******/ return __webpack_require__(0);
41+
/******/ })
42+
/************************************************************************/
43+
/******/ ([
44+
/* 0 */
45+
/***/ function(module, exports, __webpack_require__) {
46+
47+
"use strict";
48+
var a = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"a\""); e.code = 'MODULE_NOT_FOUND'; throw e; }()));
49+
console.log(a);
50+
51+
52+
/***/ }
53+
/******/ ]);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/******/ (function(modules) { // webpackBootstrap
2+
/******/ // The module cache
3+
/******/ var installedModules = {};
4+
5+
/******/ // The require function
6+
/******/ function __webpack_require__(moduleId) {
7+
8+
/******/ // Check if module is in cache
9+
/******/ if(installedModules[moduleId])
10+
/******/ return installedModules[moduleId].exports;
11+
12+
/******/ // Create a new module (and put it into the cache)
13+
/******/ var module = installedModules[moduleId] = {
14+
/******/ exports: {},
15+
/******/ id: moduleId,
16+
/******/ loaded: false
17+
/******/ };
18+
19+
/******/ // Execute the module function
20+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21+
22+
/******/ // Flag the module as loaded
23+
/******/ module.loaded = true;
24+
25+
/******/ // Return the exports of the module
26+
/******/ return module.exports;
27+
/******/ }
28+
29+
30+
/******/ // expose the modules object (__webpack_modules__)
31+
/******/ __webpack_require__.m = modules;
32+
33+
/******/ // expose the module cache
34+
/******/ __webpack_require__.c = installedModules;
35+
36+
/******/ // __webpack_public_path__
37+
/******/ __webpack_require__.p = "";
38+
39+
/******/ // Load entry module and return exports
40+
/******/ return __webpack_require__(0);
41+
/******/ })
42+
/************************************************************************/
43+
/******/ ([
44+
/* 0 */
45+
/***/ function(module, exports, __webpack_require__) {
46+
47+
"use strict";
48+
var a = __webpack_require__(1);
49+
console.log(a);
50+
51+
52+
/***/ },
53+
/* 1 */
54+
/***/ function(module, exports) {
55+
56+
"use strict";
57+
var elephant = "In the room";
58+
module.exports = elephant;
59+
60+
61+
/***/ }
62+
/******/ ]);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Asset Size Chunks Chunk Names
2+
bundle.js 1.6 kB 0 [emitted] main
3+
chunk {0} bundle.js (main) 123 bytes [rendered]
4+
[0] ./.test/nodeModulesMeaningfulErrorWhenImportingTs/app.ts 52 bytes {0} [built]
5+
[1] ./.test/nodeModulesMeaningfulErrorWhenImportingTs/~/a/index.ts 71 bytes {0} [built]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Asset Size Chunks Chunk Names
2+
bundle.js 1.6 kB 0 [emitted] main
3+
chunk {0} bundle.js (main) 52 bytes [rendered]
4+
[0] ./.test/nodeModulesMeaningfulErrorWhenImportingTs/app.ts 52 bytes {0} [built] [1 error]
5+
6+
ERROR in ./.test/nodeModulesMeaningfulErrorWhenImportingTs/~/a/index.ts
7+
Module build failed: Error: Typescript emitted no output for node_modules\a\index.ts.
8+
You should not need to recompile .ts files in node_modules.
9+
Please contact the package author to advise them to use --declaration --outDir.
10+
More https://github.com/Microsoft/TypeScript/issues/12358
11+
at Object.loader (dist\index.js:30:15)
12+
@ ./.test/nodeModulesMeaningfulErrorWhenImportingTs/app.ts 2:8-20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/******/ (function(modules) { // webpackBootstrap
2+
/******/ // The module cache
3+
/******/ var installedModules = {};
4+
5+
/******/ // The require function
6+
/******/ function __webpack_require__(moduleId) {
7+
8+
/******/ // Check if module is in cache
9+
/******/ if(installedModules[moduleId])
10+
/******/ return installedModules[moduleId].exports;
11+
12+
/******/ // Create a new module (and put it into the cache)
13+
/******/ var module = installedModules[moduleId] = {
14+
/******/ exports: {},
15+
/******/ id: moduleId,
16+
/******/ loaded: false
17+
/******/ };
18+
19+
/******/ // Execute the module function
20+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21+
22+
/******/ // Flag the module as loaded
23+
/******/ module.loaded = true;
24+
25+
/******/ // Return the exports of the module
26+
/******/ return module.exports;
27+
/******/ }
28+
29+
30+
/******/ // expose the modules object (__webpack_modules__)
31+
/******/ __webpack_require__.m = modules;
32+
33+
/******/ // expose the module cache
34+
/******/ __webpack_require__.c = installedModules;
35+
36+
/******/ // __webpack_public_path__
37+
/******/ __webpack_require__.p = "";
38+
39+
/******/ // Load entry module and return exports
40+
/******/ return __webpack_require__(0);
41+
/******/ })
42+
/************************************************************************/
43+
/******/ ([
44+
/* 0 */
45+
/***/ function(module, exports, __webpack_require__) {
46+
47+
"use strict";
48+
var a = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"a\""); e.code = 'MODULE_NOT_FOUND'; throw e; }()));
49+
console.log(a);
50+
51+
52+
/***/ }
53+
/******/ ]);

0 commit comments

Comments
 (0)