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
[WIP] feat: per module inlineDynamicImport #3299
base: master
Are you sure you want to change the base?
Changes from all commits
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 |
---|---|---|
@@ -0,0 +1,16 @@ | ||
module.exports = { | ||
description: 'inlines dynamic imports with side-effects that are only executed conditionally', | ||
options: { | ||
input: 'main.js', | ||
plugins: { | ||
transform(code, id) { | ||
if (id.endsWith('inlined.js')) { | ||
return { | ||
code, | ||
inlineDynamicImport: true | ||
}; | ||
} | ||
} | ||
} | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
define(function () { 'use strict'; | ||
|
||
if (globalThis.unknown) { | ||
Promise.resolve().then(function () { return inlined; }).then(console.log); | ||
} | ||
|
||
console.log('main1'); | ||
|
||
console.log('inlined'); | ||
const value = 'inlined'; | ||
|
||
var inlined = /*#__PURE__*/Object.freeze({ | ||
__proto__: null, | ||
value: value | ||
}); | ||
|
||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
'use strict'; | ||
|
||
if (globalThis.unknown) { | ||
Promise.resolve().then(function () { return inlined; }).then(console.log); | ||
} | ||
|
||
console.log('main1'); | ||
|
||
console.log('inlined'); | ||
const value = 'inlined'; | ||
|
||
var inlined = /*#__PURE__*/Object.freeze({ | ||
__proto__: null, | ||
value: value | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
if (globalThis.unknown) { | ||
Promise.resolve().then(function () { return inlined; }).then(console.log); | ||
} | ||
|
||
console.log('main1'); | ||
|
||
console.log('inlined'); | ||
const value = 'inlined'; | ||
|
||
var inlined = /*#__PURE__*/Object.freeze({ | ||
__proto__: null, | ||
value: value | ||
}); | ||
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 the single biggest problem I encountered with the current implementation of this feature: The dynamic imports are no longer conditionally executed, they are immediately and synchronously executed. See this example: If 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. Ok, it could technically be done by first dynamically importing the static dependencies that are in other chunks and THEN executing the conditionally imported code. But it would become quite a bit bigger than it is now because then we need to think about the whole chunk rendering process, not only the colouring algorithm. If we want to go there, I would suggest we should collect a few scenarios with expected sample code first before thinking about the implementation. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
System.register([], function () { | ||
'use strict'; | ||
return { | ||
execute: function () { | ||
|
||
if (globalThis.unknown) { | ||
Promise.resolve().then(function () { return inlined; }).then(console.log); | ||
} | ||
|
||
console.log('main1'); | ||
|
||
console.log('inlined'); | ||
const value = 'inlined'; | ||
|
||
var inlined = /*#__PURE__*/Object.freeze({ | ||
__proto__: null, | ||
value: value | ||
}); | ||
|
||
} | ||
}; | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
console.log('inlined'); | ||
export const value = 'inlined'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
if (globalThis.unknown) { | ||
import('./inlined.js').then(console.log); | ||
} | ||
|
||
console.log('main1'); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
|
||
module.exports = { | ||
description: 'inlines dynamic imports marked for inlining', | ||
options: { | ||
input: 'main.js', | ||
plugins: { | ||
resolveId(id, importer) { | ||
if (id.endsWith('dep-inlined-via-resolveId.js')) { | ||
return this.resolve(id, importer, { skipSelf: true }).then(resolution => | ||
Object.assign({}, resolution, { inlineDynamicImport: true }) | ||
); | ||
} | ||
}, | ||
load(id) { | ||
if (id.endsWith('dep-inlined-via-load.js')) { | ||
return { | ||
code: fs.readFileSync(path.resolve(__dirname, 'dep-inlined-via-load.js'), { | ||
encoding: 'utf8' | ||
}), | ||
inlineDynamicImport: true | ||
}; | ||
} | ||
}, | ||
transform(code, id) { | ||
if (id.endsWith('dep-inlined-via-transform.js')) { | ||
return { | ||
code, | ||
inlineDynamicImport: true | ||
}; | ||
} | ||
} | ||
} | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
define(['exports'], function (exports) { 'use strict'; | ||
|
||
console.log('not inlined'); | ||
const value = 'not inlined'; | ||
|
||
exports.value = value; | ||
|
||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
define(['require'], function (require) { 'use strict'; | ||
|
||
Promise.resolve().then(function () { return depInlinedViaResolveId; }).then(console.log); | ||
Promise.resolve().then(function () { return depInlinedViaLoad; }).then(console.log); | ||
Promise.resolve().then(function () { return depInlinedViaTransform; }).then(console.log); | ||
new Promise(function (resolve, reject) { require(['./generated-dep-not-inlined'], resolve, reject) }).then(console.log); | ||
|
||
console.log('main'); | ||
|
||
console.log('resolveId'); | ||
const value = 'resolveId'; | ||
|
||
var depInlinedViaResolveId = /*#__PURE__*/Object.freeze({ | ||
__proto__: null, | ||
value: value | ||
}); | ||
|
||
console.log('load'); | ||
const value$1 = 'load'; | ||
|
||
var depInlinedViaLoad = /*#__PURE__*/Object.freeze({ | ||
__proto__: null, | ||
value: value$1 | ||
}); | ||
|
||
console.log('transform'); | ||
const value$2 = 'transform'; | ||
|
||
var depInlinedViaTransform = /*#__PURE__*/Object.freeze({ | ||
__proto__: null, | ||
value: value$2 | ||
}); | ||
|
||
}); |
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 do not think this is how we should do it. The reason is that
module.dependencies
is responsible for which imports the chunk has that this module ends up in. This means that if the target of the inlined dynamic import ends up in a different chunk than the import expression, this chunk will generate both the dynamic import as well as a static one. I added a test that show-cases this.