Skip to content
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

Add isEntry flag to resolveId and this.resolve #4230

Merged
merged 5 commits into from Oct 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 5 additions & 2 deletions browser/resolveId.ts
Expand Up @@ -12,18 +12,21 @@ export async function resolveId(
source: string,
importer: string | undefined,
customOptions: CustomPluginOptions | undefined,
isEntry: boolean | undefined,
skip: { importer: string | undefined; plugin: Plugin; source: string }[] | null
) => Promise<ResolvedId | null>,
skip: { importer: string | undefined; plugin: Plugin; source: string }[] | null,
customOptions: CustomPluginOptions | undefined
customOptions: CustomPluginOptions | undefined,
isEntry: boolean
): Promise<ResolveIdResult> {
const pluginResult = await resolveIdViaPlugins(
source,
importer,
pluginDriver,
moduleLoaderResolveId,
skip,
customOptions
customOptions,
isEntry
);
if (pluginResult == null) {
throwNoFileSystem('path.resolve');
Expand Down
3 changes: 1 addition & 2 deletions docs/01-command-line-reference.md
Expand Up @@ -448,7 +448,7 @@ Print the installed version number.

Rebuild the bundle when its source files change on disk.

_Note: While in watch mode, the `ROLLUP_WATCH` environment variable will be set to `"true"` by Rollup's command line interface and can be checked by other processes. Plugins should instead check [`this.meta.watchMode`](guide/en/#thismeta-rollupversion-string-watchmode-boolean), which is independent of the command line interface._
_Note: While in watch mode, the `ROLLUP_WATCH` environment variable will be set to `"true"` by Rollup's command line interface and can be checked by other processes. Plugins should instead check [`this.meta.watchMode`](guide/en/#thismeta), which is independent of the command line interface._

#### `--silent`

Expand All @@ -469,7 +469,6 @@ rollup -c --environment INCLUDE_DEPS,BUILD:production
will set `process.env.INCLUDE_DEPS === 'true'` and `process.env.BUILD === 'production'`. You can use this option several times. In that case, subsequently set variables will overwrite previous definitions. This enables you for instance to overwrite environment variables in `package.json` scripts:

```json
// in package.json
{
"scripts": {
"build": "rollup -c --environment INCLUDE_DEPS,BUILD:production"
Expand Down
459 changes: 257 additions & 202 deletions docs/05-plugin-development.md

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions docs/999-big-list-of-options.md
Expand Up @@ -91,7 +91,7 @@ export default {
};
```

The option can be omitted if some plugin emits at least one chunk (using [`this.emitFile`](guide/en/#thisemitfileemittedfile-emittedchunk--emittedasset--string)) by the end of the [`buildStart`](guide/en/#buildstart) hook.
The option can be omitted if some plugin emits at least one chunk (using [`this.emitFile`](guide/en/#thisemitfile)) by the end of the [`buildStart`](guide/en/#buildstart) hook.

When using the command line interface, multiple inputs can be provided by using the option multiple times. When provided as the first options, it is equivalent to not prefix them with `--input`:

Expand Down Expand Up @@ -422,7 +422,7 @@ The pattern to use for naming shared chunks created when code-splitting, or a fu

- `[format]`: The rendering format defined in the output options, e.g. `es` or `cjs`.
- `[hash]`: A hash based on the content of the chunk and the content of all its dependencies.
- `[name]`: The name of the chunk. This can be explicitly set via the [`output.manualChunks`](guide/en/#outputmanualchunks) option or when the chunk is created by a plugin via [`this.emitFile`](guide/en/#thisemitfileemittedfile-emittedchunk--emittedasset--string). Otherwise, it will be derived from the chunk contents.
- `[name]`: The name of the chunk. This can be explicitly set via the [`output.manualChunks`](guide/en/#outputmanualchunks) option or when the chunk is created by a plugin via [`this.emitFile`](guide/en/#thisemitfile). Otherwise, it will be derived from the chunk contents.

Forward slashes `/` can be used to place files in sub-directories. When using a function, `chunkInfo` is a reduced version of the one in [`generateBundle`](guide/en/#generatebundle) without properties that depend on file names. See also [`output.assetFileNames`](guide/en/#outputassetfilenames), [`output.entryFileNames`](guide/en/#outputentryfilenames).

Expand Down Expand Up @@ -823,7 +823,7 @@ manualChunks(id) {

Be aware that manual chunks can change the behaviour of the application if side effects are triggered before the corresponding modules are actually used.

When using the function form, `manualChunks` will be passed an object as second parameter containing the functions `getModuleInfo` and `getModuleIds` that work the same way as [`this.getModuleInfo`](guide/en/#thisgetmoduleinfomoduleid-string--moduleinfo--null) and [`this.getModuleIds`](guide/en/#thisgetmoduleids--iterableiteratorstring) on the plugin context.
When using the function form, `manualChunks` will be passed an object as second parameter containing the functions `getModuleInfo` and `getModuleIds` that work the same way as [`this.getModuleInfo`](guide/en/#thisgetmoduleinfo) and [`this.getModuleIds`](guide/en/#thisgetmoduleids) on the plugin context.

This can be used to dynamically determine into which manual chunk a module should be placed depending on its position in the module graph. For instance consider a scenario where you have a set of components, each of which dynamically imports a set of translated strings, i.e.

Expand Down Expand Up @@ -1169,7 +1169,7 @@ const shared = 'shared';
console.log(shared);
```

At the moment, the only way to override this setting for individual entry chunks is to use the plugin API and emit those chunks via [`this.emitFile`](guide/en/#thisemitfileemittedfile-emittedchunk--emittedasset--string) instead of using the [`input`](guide/en/#input) option.
At the moment, the only way to override this setting for individual entry chunks is to use the plugin API and emit those chunks via [`this.emitFile`](guide/en/#thisemitfile) instead of using the [`input`](guide/en/#input) option.

#### strictDeprecations

Expand Down
11 changes: 7 additions & 4 deletions src/ModuleLoader.ts
Expand Up @@ -149,6 +149,7 @@ export class ModuleLoader {
source: string,
importer: string | undefined,
customOptions: CustomPluginOptions | undefined,
isEntry: boolean | undefined,
skip: { importer: string | undefined; plugin: Plugin; source: string }[] | null = null
): Promise<ResolvedId | null> => {
return this.addDefaultsToResolvedId(
Expand All @@ -162,7 +163,8 @@ export class ModuleLoader {
this.pluginDriver,
this.resolveId,
skip,
customOptions
customOptions,
typeof isEntry === 'boolean' ? isEntry : !importer
),

importer,
Expand Down Expand Up @@ -483,7 +485,7 @@ export class ModuleLoader {
(module.resolvedIds[source] =
module.resolvedIds[source] ||
this.handleResolveId(
await this.resolveId(source, module.id, EMPTY_OBJECT),
await this.resolveId(source, module.id, EMPTY_OBJECT, false),
source,
module.id
))
Expand Down Expand Up @@ -529,7 +531,8 @@ export class ModuleLoader {
this.pluginDriver,
this.resolveId,
null,
EMPTY_OBJECT
EMPTY_OBJECT,
true
);
if (resolveIdResult == null) {
return error(
Expand Down Expand Up @@ -585,7 +588,7 @@ export class ModuleLoader {
return (module.resolvedIds[specifier] =
module.resolvedIds[specifier] ||
this.handleResolveId(
await this.resolveId(specifier, module.id, EMPTY_OBJECT),
await this.resolveId(specifier, module.id, EMPTY_OBJECT, false),
specifier,
module.id
));
Expand Down
4 changes: 2 additions & 2 deletions src/rollup/types.d.ts
Expand Up @@ -204,7 +204,7 @@ export interface PluginContext extends MinimalPluginContext {
resolve: (
source: string,
importer?: string,
options?: { custom?: CustomPluginOptions; skipSelf?: boolean }
options?: { custom?: CustomPluginOptions; isEntry?: boolean; skipSelf?: boolean }
) => Promise<ResolvedId | null>;
/** @deprecated Use `this.resolve` instead */
resolveId: (source: string, importer?: string) => Promise<string | null>;
Expand Down Expand Up @@ -237,7 +237,7 @@ export type ResolveIdHook = (
this: PluginContext,
source: string,
importer: string | undefined,
options: { custom?: CustomPluginOptions }
options: { custom?: CustomPluginOptions; isEntry: boolean }
) => Promise<ResolveIdResult> | ResolveIdResult;

export type IsExternal = (
Expand Down
5 changes: 3 additions & 2 deletions src/utils/PluginContext.ts
Expand Up @@ -157,18 +157,19 @@ export function getPluginContext(
return wrappedModuleIds();
},
parse: graph.contextParse.bind(graph),
resolve(source, importer, { custom, skipSelf } = BLANK) {
resolve(source, importer, { custom, isEntry, skipSelf } = BLANK) {
return graph.moduleLoader.resolveId(
source,
importer,
custom,
isEntry,
skipSelf ? [{ importer, plugin, source }] : null
);
},
resolveId: getDeprecatedContextHandler(
(source: string, importer: string | undefined) =>
graph.moduleLoader
.resolveId(source, importer, BLANK)
.resolveId(source, importer, BLANK, undefined)
.then(resolveId => resolveId && resolveId.id),
'resolveId',
'resolve',
Expand Down
7 changes: 5 additions & 2 deletions src/utils/resolveId.ts
Expand Up @@ -13,18 +13,21 @@ export async function resolveId(
source: string,
importer: string | undefined,
customOptions: CustomPluginOptions | undefined,
isEntry: boolean | undefined,
skip: { importer: string | undefined; plugin: Plugin; source: string }[] | null
) => Promise<ResolvedId | null>,
skip: { importer: string | undefined; plugin: Plugin; source: string }[] | null,
customOptions: CustomPluginOptions | undefined
customOptions: CustomPluginOptions | undefined,
isEntry: boolean
): Promise<ResolveIdResult> {
const pluginResult = await resolveIdViaPlugins(
source,
importer,
pluginDriver,
moduleLoaderResolveId,
skip,
customOptions
customOptions,
isEntry
);
if (pluginResult != null) return pluginResult;

Expand Down
9 changes: 6 additions & 3 deletions src/utils/resolveIdViaPlugins.ts
Expand Up @@ -16,10 +16,12 @@ export function resolveIdViaPlugins(
source: string,
importer: string | undefined,
customOptions: CustomPluginOptions | undefined,
isEntry: boolean | undefined,
skip: { importer: string | undefined; plugin: Plugin; source: string }[] | null
) => Promise<ResolvedId | null>,
skip: { importer: string | undefined; plugin: Plugin; source: string }[] | null,
customOptions: CustomPluginOptions | undefined
customOptions: CustomPluginOptions | undefined,
isEntry: boolean
): Promise<ResolveIdResult> {
let skipped: Set<Plugin> | null = null;
let replaceContext: ReplaceContext | null = null;
Expand All @@ -32,19 +34,20 @@ export function resolveIdViaPlugins(
}
replaceContext = (pluginContext, plugin): PluginContext => ({
...pluginContext,
resolve: (source, importer, { custom, skipSelf } = BLANK) => {
resolve: (source, importer, { custom, isEntry, skipSelf } = BLANK) => {
return moduleLoaderResolveId(
source,
importer,
custom,
isEntry,
skipSelf ? [...skip, { importer, plugin, source }] : skip
);
}
});
}
return pluginDriver.hookFirst(
'resolveId',
[source, importer, { custom: customOptions }],
[source, importer, { custom: customOptions, isEntry }],
replaceContext,
skipped
);
Expand Down
4 changes: 2 additions & 2 deletions test/function/index.js
Expand Up @@ -48,7 +48,7 @@ function runCodeSplitTest(codeMap, entryId, configContext) {
return { exports };
}

runTestSuiteWithSamples('function', path.resolve(__dirname, 'samples'), (dir, config) => {
runTestSuiteWithSamples('function', path.join(__dirname, 'samples'), (dir, config) => {
(config.skip ? it.skip : config.solo ? it.only : it)(
path.basename(dir) + ': ' + config.description,
() => {
Expand All @@ -59,7 +59,7 @@ runTestSuiteWithSamples('function', path.resolve(__dirname, 'samples'), (dir, co

return rollup
.rollup({
input: dir + '/main.js',
input: path.join(dir, 'main.js'),
onwarn: warning => warnings.push(warning),
strictDeprecations: true,
...(config.options || {})
Expand Down
72 changes: 72 additions & 0 deletions test/function/samples/resolveid-is-entry/_config.js
@@ -0,0 +1,72 @@
const assert = require('assert');
const path = require('path');

const ID_MAIN = path.join(__dirname, 'main.js');

module.exports = {
description: 'sends correct isEntry information to resolveId hooks',
options: {
plugins: [
{
async buildStart() {
return Promise.all([
this.emitFile({ type: 'chunk', id: 'chunkWithoutImporter.js' }),
this.emitFile({ type: 'chunk', id: './chunkWithImporter.js', importer: ID_MAIN }),
this.resolve('./resolutionWithoutImporter'),
this.resolve('./resolutionWithoutImporterEntry', undefined, { isEntry: true }),
this.resolve('./resolutionWithoutImporterNonEntry', undefined, { isEntry: false }),
this.resolve('./resolutionWithImporter', ID_MAIN),
this.resolve('./resolutionWithImporterEntry', ID_MAIN, { isEntry: true }),
this.resolve('./resolutionWithImporterNonEntry', ID_MAIN, { isEntry: false })
]);
},
resolveId(source, importer, { isEntry }) {
switch (source) {
case ID_MAIN:
assert.strictEqual(importer, undefined, source);
assert.strictEqual(isEntry, true, source);
break;
case './dep.js':
assert.strictEqual(importer, ID_MAIN, source);
assert.strictEqual(isEntry, false, source);
break;
case 'chunkWithoutImporter.js':
assert.strictEqual(importer, undefined, source);
assert.strictEqual(isEntry, true, source);
break;
case './chunkWithImporter.js':
assert.strictEqual(importer, ID_MAIN, source);
assert.strictEqual(isEntry, true, source);
break;
case './resolutionWithoutImporter':
assert.strictEqual(importer, undefined, source);
assert.strictEqual(isEntry, true, source);
break;
case './resolutionWithoutImporterEntry':
assert.strictEqual(importer, undefined, source);
assert.strictEqual(isEntry, true, source);
break;
case './resolutionWithoutImporterNonEntry':
assert.strictEqual(importer, undefined, source);
assert.strictEqual(isEntry, false, source);
break;
case './resolutionWithImporter':
assert.strictEqual(importer, ID_MAIN, source);
assert.strictEqual(isEntry, false, source);
break;
case './resolutionWithImporterEntry':
assert.strictEqual(importer, ID_MAIN, source);
assert.strictEqual(isEntry, true, source);
break;
case './resolutionWithImporterNonEntry':
assert.strictEqual(importer, ID_MAIN, source);
assert.strictEqual(isEntry, false, source);
break;
default:
throw new Error(`Unexpected resolution of ${source}`);
}
}
}
]
}
};
@@ -0,0 +1 @@
console.log('with');
@@ -0,0 +1 @@
console.log('without');
1 change: 1 addition & 0 deletions test/function/samples/resolveid-is-entry/dep.js
@@ -0,0 +1 @@
export default 42;
3 changes: 3 additions & 0 deletions test/function/samples/resolveid-is-entry/main.js
@@ -0,0 +1,3 @@
import value from './dep.js';

assert.strictEqual(value, 42);
@@ -0,0 +1 @@
console.log('with');
@@ -0,0 +1 @@
console.log('with entry');
@@ -0,0 +1 @@
console.log('with non entry');
@@ -0,0 +1 @@
console.log('without');
@@ -0,0 +1 @@
console.log('without entry');
@@ -0,0 +1 @@
console.log('without non entry');
4 changes: 2 additions & 2 deletions test/utils.js
Expand Up @@ -123,7 +123,7 @@ function runSamples(samplesDir, runTest, onTeardown) {
.readdirSync(samplesDir)
.filter(name => name[0] !== '.')
.sort()
.forEach(fileName => runTestsInDir(samplesDir + '/' + fileName, runTest));
.forEach(fileName => runTestsInDir(path.join(samplesDir, fileName), runTest));
}

function runTestsInDir(dir, runTest) {
Expand All @@ -138,7 +138,7 @@ function runTestsInDir(dir, runTest) {
fileNames
.filter(name => name[0] !== '.')
.sort()
.forEach(fileName => runTestsInDir(dir + '/' + fileName, runTest));
.forEach(fileName => runTestsInDir(path.join(dir, fileName), runTest));
});
}
}
Expand Down