Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17143 from webpack/issue-16838
fix: use rel modulepreload for esm modules
- Loading branch information
Showing
9 changed files
with
215 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export default function() { | ||
import(/* webpackPrefetch: true, webpackChunkName: "chunk1-a" */ "./chunk1-a"); | ||
import(/* webpackPreload: true, webpackChunkName: "chunk1-b" */ "./chunk1-b"); | ||
import(/* webpackPrefetch: 10, webpackChunkName: "chunk1-c" */ "./chunk1-c"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export default function() { | ||
import(/* webpackPrefetch: true, webpackChunkName: "chunk1-a" */ "./chunk1-a"); | ||
import(/* webpackPreload: true, webpackChunkName: "chunk1-b" */ "./chunk1-b"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// This config need to be set on initial evaluation to be effective | ||
__webpack_nonce__ = "nonce"; | ||
__webpack_public_path__ = "https://example.com/public/path/"; | ||
|
||
it("should prefetch and preload child chunks on chunk load", () => { | ||
let link, script; | ||
|
||
expect(document.head._children).toHaveLength(1); | ||
|
||
// Test prefetch from entry chunk | ||
link = document.head._children[0]; | ||
expect(link._type).toBe("link"); | ||
expect(link.rel).toBe("prefetch"); | ||
expect(link.href).toBe("https://example.com/public/path/chunk1.js"); | ||
|
||
const promise = import( | ||
/* webpackChunkName: "chunk1", webpackPrefetch: true */ "./chunk1" | ||
); | ||
|
||
expect(document.head._children).toHaveLength(3); | ||
|
||
// Test normal script loading | ||
script = document.head._children[1]; | ||
expect(script._type).toBe("script"); | ||
expect(script.src).toBe("https://example.com/public/path/chunk1.js"); | ||
expect(script.getAttribute("nonce")).toBe("nonce"); | ||
expect(script.crossOrigin).toBe("anonymous"); | ||
expect(script.onload).toBeTypeOf("function"); | ||
|
||
// Test preload of chunk1-b | ||
link = document.head._children[2]; | ||
expect(link._type).toBe("link"); | ||
expect(link.rel).toBe("preload"); | ||
expect(link.as).toBe("script"); | ||
expect(link.href).toBe("https://example.com/public/path/chunk1-b.js"); | ||
expect(link.charset).toBe("utf-8"); | ||
expect(link.getAttribute("nonce")).toBe("nonce"); | ||
expect(link.crossOrigin).toBe("anonymous"); | ||
|
||
// Run the script | ||
__non_webpack_require__("./chunk1.js"); | ||
|
||
script.onload(); | ||
|
||
return promise.then(() => { | ||
expect(document.head._children).toHaveLength(4); | ||
|
||
// Test prefetching for chunk1-c and chunk1-a in this order | ||
link = document.head._children[2]; | ||
expect(link._type).toBe("link"); | ||
expect(link.rel).toBe("prefetch"); | ||
expect(link.href).toBe("https://example.com/public/path/chunk1-c.js"); | ||
expect(link.crossOrigin).toBe("anonymous"); | ||
|
||
link = document.head._children[3]; | ||
expect(link._type).toBe("link"); | ||
expect(link.rel).toBe("prefetch"); | ||
expect(link.href).toBe("https://example.com/public/path/chunk1-a.js"); | ||
expect(link.crossOrigin).toBe("anonymous"); | ||
|
||
const promise2 = import( | ||
/* webpackChunkName: "chunk1", webpackPrefetch: true */ "./chunk1" | ||
); | ||
|
||
// Loading chunk1 again should not trigger prefetch/preload | ||
expect(document.head._children).toHaveLength(4); | ||
|
||
const promise3 = import(/* webpackChunkName: "chunk2" */ "./chunk2"); | ||
|
||
expect(document.head._children).toHaveLength(5); | ||
|
||
// Test normal script loading | ||
script = document.head._children[4]; | ||
expect(script._type).toBe("script"); | ||
expect(script.src).toBe("https://example.com/public/path/chunk2.js"); | ||
expect(script.getAttribute("nonce")).toBe("nonce"); | ||
expect(script.crossOrigin).toBe("anonymous"); | ||
expect(script.onload).toBeTypeOf("function"); | ||
|
||
// Run the script | ||
__non_webpack_require__("./chunk2.js"); | ||
|
||
script.onload(); | ||
|
||
return promise3.then(() => { | ||
// Loading chunk2 again should not trigger prefetch/preload as it's already prefetch/preloaded | ||
expect(document.head._children).toHaveLength(4); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// This config need to be set on initial evaluation to be effective | ||
__webpack_nonce__ = "nonce"; | ||
__webpack_public_path__ = "https://example.com/public/path/"; | ||
|
||
it("should prefetch and preload child chunks on chunk load", () => { | ||
let link, script; | ||
|
||
expect(document.head._children).toHaveLength(1); | ||
|
||
// Test prefetch from entry chunk | ||
link = document.head._children[0]; | ||
expect(link._type).toBe("link"); | ||
expect(link.rel).toBe("prefetch"); | ||
expect(link.href).toBe("https://example.com/public/path/chunk1.js"); | ||
|
||
const promise = import( | ||
/* webpackChunkName: "chunk1", webpackPrefetch: true */ "./chunk1.js" | ||
); | ||
|
||
expect(document.head._children).toHaveLength(3); | ||
|
||
// Test normal script loading | ||
script = document.head._children[1]; | ||
expect(script._type).toBe("script"); | ||
expect(script.src).toBe("https://example.com/public/path/chunk1.js"); | ||
expect(script.getAttribute("nonce")).toBe("nonce"); | ||
expect(script.crossOrigin).toBe("anonymous"); | ||
expect(script.onload).toBeTypeOf("function"); | ||
|
||
// Test preload of chunk1-b | ||
link = document.head._children[2]; | ||
expect(link._type).toBe("link"); | ||
expect(link.rel).toBe("modulepreload"); | ||
expect(link.href).toBe("https://example.com/public/path/chunk1-b.js"); | ||
expect(link.charset).toBe("utf-8"); | ||
expect(link.getAttribute("nonce")).toBe("nonce"); | ||
expect(link.crossOrigin).toBe("anonymous"); | ||
|
||
// Run the script | ||
__non_webpack_require__("./chunk1.js"); | ||
|
||
script.onload(); | ||
|
||
return promise.then(() => { | ||
expect(document.head._children).toHaveLength(4); | ||
|
||
// Test prefetching for chunk1-c and chunk1-a in this order | ||
link = document.head._children[2]; | ||
expect(link._type).toBe("link"); | ||
expect(link.rel).toBe("prefetch"); | ||
expect(link.href).toBe("https://example.com/public/path/chunk1-c.js"); | ||
expect(link.crossOrigin).toBe("anonymous"); | ||
|
||
link = document.head._children[3]; | ||
expect(link._type).toBe("link"); | ||
expect(link.rel).toBe("prefetch"); | ||
expect(link.href).toBe("https://example.com/public/path/chunk1-a.js"); | ||
expect(link.crossOrigin).toBe("anonymous"); | ||
|
||
const promise2 = import( | ||
/* webpackChunkName: "chunk1", webpackPrefetch: true */ "./chunk1.js" | ||
); | ||
|
||
// Loading chunk1 again should not trigger prefetch/preload | ||
expect(document.head._children).toHaveLength(4); | ||
|
||
const promise3 = import(/* webpackChunkName: "chunk2" */ "./chunk2.js"); | ||
|
||
expect(document.head._children).toHaveLength(5); | ||
|
||
// Test normal script loading | ||
script = document.head._children[4]; | ||
expect(script._type).toBe("script"); | ||
expect(script.src).toBe("https://example.com/public/path/chunk2.js"); | ||
expect(script.getAttribute("nonce")).toBe("nonce"); | ||
expect(script.crossOrigin).toBe("anonymous"); | ||
expect(script.onload).toBeTypeOf("function"); | ||
|
||
// Run the script | ||
__non_webpack_require__("./chunk2.js"); | ||
|
||
script.onload(); | ||
|
||
return promise3.then(() => { | ||
// Loading chunk2 again should not trigger prefetch/preload as it's already prefetch/preloaded | ||
expect(document.head._children).toHaveLength(4); | ||
}); | ||
}); | ||
}); |
22 changes: 22 additions & 0 deletions
22
test/configCases/web/prefetch-preload-module/webpack.config.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/** @type {import("../../../../").Configuration} */ | ||
module.exports = { | ||
entry: "./index.mjs", | ||
experiments: { | ||
outputModule: true | ||
}, | ||
name: "esm", | ||
target: "web", | ||
output: { | ||
publicPath: "", | ||
module: true, | ||
filename: "bundle0.js", | ||
chunkFilename: "[name].js", | ||
crossOriginLoading: "anonymous" | ||
}, | ||
performance: { | ||
hints: false | ||
}, | ||
optimization: { | ||
minimize: false | ||
} | ||
}; |