-
-
Notifications
You must be signed in to change notification settings - Fork 433
Set webpack module type to "javascript/esm"
when TS impliedNodeFormat
is ESNext
#1614
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
d490c50
c3fc615
4712067
394c7a7
3ea6e50
a2cbf15
6d31cf6
379e771
2888b33
e436dd0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,7 @@ import { | |
appendSuffixesIfMatch, | ||
ensureProgram, | ||
formatErrors, | ||
getImpliedNodeFormat, | ||
isReferencedFile, | ||
makeError, | ||
supportsSolutionBuild, | ||
|
@@ -363,7 +364,7 @@ export function initializeInstance( | |
: instance.compiler.createProgram([], instance.compilerOptions)); | ||
|
||
const getProgram = () => program; | ||
instance.transformers = getCustomTransformers(instance.loaderOptions, program, getProgram); | ||
instance.transformers = getCustomTransformers(instance, loader, program, getProgram); | ||
// Setup watch run for solution building | ||
if (instance.solutionBuilderHost) { | ||
addAssetHooks(loader, instance); | ||
|
@@ -394,11 +395,12 @@ export function initializeInstance( | |
instance.builderProgram = | ||
instance.watchOfFilesAndCompilerOptions.getProgram(); | ||
|
||
const getProgram = () => instance.builderProgram?.getProgram(); | ||
const getProgram = () => instance.builderProgram!.getProgram(); | ||
instance.program = getProgram(); | ||
instance.transformers = getCustomTransformers( | ||
instance.loaderOptions, | ||
instance.program, | ||
instance, | ||
loader, | ||
instance.program!, | ||
getProgram | ||
); | ||
} else { | ||
|
@@ -414,8 +416,8 @@ export function initializeInstance( | |
instance.compiler.createDocumentRegistry() | ||
); | ||
|
||
const getProgram = () => instance.languageService!.getProgram(); | ||
instance.transformers = getCustomTransformers(instance.loaderOptions, getProgram(), getProgram); | ||
const getProgram = () => instance.languageService!.getProgram()!; | ||
instance.transformers = getCustomTransformers(instance, loader, getProgram(), getProgram); | ||
} | ||
|
||
addAssetHooks(loader, instance); | ||
|
@@ -427,14 +429,25 @@ export function initializeInstance( | |
} | ||
} | ||
|
||
function getSetImpliedNodeFormatTransformer(instance: TSInstance, loaderContext: webpack.LoaderContext<LoaderOptions>, getProgram: () => typescript.Program) { | ||
return (): typescript.Transformer<typescript.SourceFile> => { | ||
return (sourceFile) => { | ||
sourceFile.impliedNodeFormat = getImpliedNodeFormat(sourceFile.fileName, instance, loaderContext, getProgram()); | ||
return sourceFile; | ||
} | ||
} | ||
} | ||
|
||
export function getCustomTransformers( | ||
loaderOptions: LoaderOptions, | ||
program: typescript.Program | undefined, | ||
getProgram: (() => typescript.Program | undefined) | undefined | ||
instance: TSInstance, | ||
loaderContext: webpack.LoaderContext<LoaderOptions>, | ||
program: typescript.Program, | ||
getProgram: (() => typescript.Program) | ||
) { | ||
// same strategy as https://github.com/s-panferov/awesome-typescript-loader/pull/531/files | ||
const { loaderOptions } = instance; | ||
let { getCustomTransformers: customerTransformers } = loaderOptions; | ||
let getCustomTransformers = Function.prototype; | ||
let getCustomTransformers; | ||
|
||
if (typeof customerTransformers === 'function') { | ||
getCustomTransformers = customerTransformers; | ||
|
@@ -459,7 +472,14 @@ export function getCustomTransformers( | |
getCustomTransformers = customerTransformers; | ||
} | ||
|
||
return getCustomTransformers(program, getProgram); | ||
let transformers = getCustomTransformers?.(program, getProgram); | ||
if (loaderOptions.transpileOnly) { | ||
(transformers ??= {}).before = [ | ||
getSetImpliedNodeFormatTransformer(instance, loaderContext, getProgram), | ||
...(transformers?.before ?? []), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
]; | ||
} | ||
return transformers; | ||
} | ||
|
||
function getScriptRegexp(instance: TSInstance) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,23 +33,21 @@ import { | |
useCaseSensitiveFileNames, | ||
} from './utils'; | ||
|
||
function makeResolversAndModuleResolutionHost( | ||
scriptRegex: RegExp, | ||
loader: webpack.LoaderContext<LoaderOptions>, | ||
export function makeModuleResolutionHost( | ||
instance: TSInstance, | ||
fileExists: (fileName: string) => boolean, | ||
enableFileCaching: boolean | ||
) { | ||
const { | ||
compiler, | ||
compilerOptions, | ||
appendTsTsxSuffixesIfRequired, | ||
loaderOptions: { | ||
resolveModuleName: customResolveModuleName, | ||
resolveTypeReferenceDirective: customResolveTypeReferenceDirective, | ||
}, | ||
} = instance; | ||
|
||
loader: webpack.LoaderContext<LoaderOptions>, | ||
enableFileCaching: boolean, | ||
fileExists?: (fileName: string) => boolean | ||
): ModuleResolutionHostMayBeCacheable { | ||
const { files, otherFiles, compiler, compilerOptions, filePathKeyMapper } = instance; | ||
fileExists ??= (fileName: string) => { | ||
const filePathKey = filePathKeyMapper(fileName); | ||
return ( | ||
files.has(filePathKey) || | ||
otherFiles.has(filePathKey) || | ||
compiler.sys.fileExists(fileName) | ||
); | ||
}; | ||
const newLine = | ||
compilerOptions.newLine === constants.CarriageReturnLineFeedCode | ||
? constants.CarriageReturnLineFeed | ||
|
@@ -60,9 +58,6 @@ function makeResolversAndModuleResolutionHost( | |
// loader.context seems to work fine on Linux / Mac regardless causes problems for @types resolution on Windows for TypeScript < 2.3 | ||
const getCurrentDirectory = () => loader.context; | ||
|
||
// make a (sync) resolver that follows webpack's rules | ||
const resolveSync = makeResolver(loader._compiler!.options); | ||
|
||
const moduleResolutionHost: ModuleResolutionHostMayBeCacheable = { | ||
trace: logData => instance.log.log(logData), | ||
fileExists, | ||
|
@@ -79,21 +74,22 @@ function makeResolversAndModuleResolutionHost( | |
getDefaultLibFileName: options => compiler.getDefaultLibFilePath(options), | ||
}; | ||
|
||
|
||
if (enableFileCaching) { | ||
addCache(moduleResolutionHost); | ||
} | ||
|
||
return makeResolvers( | ||
compiler, | ||
compilerOptions, | ||
moduleResolutionHost, | ||
customResolveTypeReferenceDirective, | ||
customResolveModuleName, | ||
resolveSync, | ||
appendTsTsxSuffixesIfRequired, | ||
scriptRegex, | ||
instance | ||
); | ||
|
||
if (!instance.moduleResolutionCache && !instance.loaderOptions.resolveModuleName) { | ||
instance.moduleResolutionCache = createModuleResolutionCache( | ||
instance, | ||
moduleResolutionHost | ||
); | ||
} | ||
|
||
instance.moduleResolutionHost = moduleResolutionHost; | ||
|
||
return moduleResolutionHost; | ||
|
||
function readFile( | ||
filePath: string, | ||
|
@@ -134,6 +130,42 @@ function makeResolversAndModuleResolutionHost( | |
} | ||
} | ||
|
||
function makeResolversAndModuleResolutionHost( | ||
scriptRegex: RegExp, | ||
loader: webpack.LoaderContext<LoaderOptions>, | ||
instance: TSInstance, | ||
fileExists: (fileName: string) => boolean, | ||
enableFileCaching: boolean | ||
) { | ||
const { | ||
compiler, | ||
compilerOptions, | ||
appendTsTsxSuffixesIfRequired, | ||
loaderOptions: { | ||
resolveModuleName: customResolveModuleName, | ||
resolveTypeReferenceDirective: customResolveTypeReferenceDirective, | ||
}, | ||
} = instance; | ||
|
||
|
||
|
||
// make a (sync) resolver that follows webpack's rules | ||
const resolveSync = makeResolver(loader._compiler!.options); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you really need this? Based on logic it is just an error - https://github.com/TypeStrong/ts-loader/blob/main/src/resolver.ts#L11 Webpack has great API for resolving, you can use (just an example of code, we should have two resolvers for cjs and esm in the real life):
And hide a lot of options for basic There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is just moved code, not code I wrote |
||
const moduleResolutionHost = makeModuleResolutionHost(instance, loader, enableFileCaching, fileExists); | ||
|
||
return makeResolvers( | ||
compiler, | ||
compilerOptions, | ||
moduleResolutionHost, | ||
customResolveTypeReferenceDirective, | ||
customResolveModuleName, | ||
resolveSync, | ||
appendTsTsxSuffixesIfRequired, | ||
scriptRegex, | ||
instance | ||
); | ||
} | ||
|
||
/** | ||
* Create the TypeScript language service | ||
*/ | ||
|
@@ -768,7 +800,7 @@ export function makeSolutionBuilderHost( | |
); | ||
|
||
// Keeps track of the various `typescript.CustomTransformers` for each program that is created. | ||
const customTransformers = new Map<string, typescript.CustomTransformers>(); | ||
const customTransformers = new Map<string, typescript.CustomTransformers | undefined>(); | ||
|
||
// let lastBuilderProgram: typescript.CreateProgram | undefined = undefined; | ||
const solutionBuilderHost: SolutionBuilderWithWatchHost = { | ||
|
@@ -802,7 +834,7 @@ export function makeSolutionBuilderHost( | |
if (typeof project === "string") { | ||
// Custom transformers need a reference to the `typescript.Program`, that reference is | ||
// unavailable during the the `getCustomTransformers` callback below. | ||
const transformers = getCustomTransformers(instance.loaderOptions, result.getProgram(), result.getProgram); | ||
const transformers = getCustomTransformers(instance, loader, result.getProgram(), result.getProgram); | ||
customTransformers.set(project, transformers); | ||
} | ||
} | ||
|
@@ -1335,12 +1367,6 @@ function makeResolveModuleName( | |
instance: TSInstance | ||
): ResolveModuleName { | ||
if (customResolveModuleName === undefined) { | ||
if (!instance.moduleResolutionCache) { | ||
instance.moduleResolutionCache = createModuleResolutionCache( | ||
instance, | ||
moduleResolutionHost | ||
); | ||
} | ||
return ( | ||
moduleName, | ||
containingFileName, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import assert from "assert"; | ||
import externalLib from "./lib/externalLib.js"; | ||
assert.deepStrictEqual(externalLib, { default: {} }); | ||
console.log("PASS"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"I got 99 problems but EcmaScript modules ain't one"