Skip to content

Commit 214f361

Browse files
authored
feat: add the context option support for VirtualUrlPlugin (#20449)
1 parent d5fc9c6 commit 214f361

13 files changed

Lines changed: 375 additions & 116 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"webpack": minor
3+
---
4+
5+
Add `context` option support for VirtualUrlPlugin
6+
7+
- The context for the virtual module. A string path. Defaults to 'auto', which will try to resolve the context from the module id.
8+
- Support custom context path for resolving relative imports in virtual modules
9+
- Add examples demonstrating context usage and filename customization

declarations/plugins/schemes/VirtualUrlPlugin.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ export type VirtualModuleContent =
1717
* Options for building virtual resources.
1818
*/
1919
export interface VirtualUrlOptions {
20+
/**
21+
* The default context for virtual modules. A string path. Defaults to 'auto', which will try to resolve the context from the module id.
22+
*/
23+
context?: string;
2024
/**
2125
* The virtual modules configuration.
2226
*/
@@ -32,6 +36,10 @@ export interface VirtualUrlOptions {
3236
* A virtual module definition.
3337
*/
3438
export interface VirtualModule {
39+
/**
40+
* The context for the virtual module. A string path. Defaults to 'auto', which will try to resolve the context from the module id.
41+
*/
42+
context?: string;
3543
/**
3644
* The source function that provides the virtual content.
3745
*/

examples/virtual-modules/README.md

Lines changed: 111 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ console.log(second); // Output `second`
3232
import message from "my-custom-scheme:my-module";
3333

3434
console.log(message); // Output `from virtual module with custom scheme`
35+
36+
// Import virtual module with custom context set in source function
37+
import { button } from "virtual:src/components/button.js";
38+
39+
console.log(button); // Output `button`
40+
41+
// Import virtual asset (filename will have virtual: scheme removed)
42+
import logoUrl from "virtual:logo.svg";
43+
44+
console.log(logoUrl); // Output path to logo.svg (without virtual: scheme)
3545
```
3646

3747
# routes/a.js
@@ -81,6 +91,15 @@ const config = (env = "development") => ({
8191
options: {
8292
transpileOnly: true
8393
}
94+
},
95+
{
96+
test: /\.(svg|png)$/,
97+
type: "asset/resource",
98+
generator: {
99+
// Remove virtual: scheme from filename
100+
filename: (/** @type {{ filename: string }} */ pathData) =>
101+
pathData.filename.replace("virtual:", "")
102+
}
84103
}
85104
]
86105
},
@@ -113,7 +132,9 @@ const value: string = "value-from-typescript";
113132
export default value;`
114133
},
115134
routes: {
116-
source(loaderContext) {
135+
source(
136+
/** @type {import("webpack").LoaderContext<unknown>} */ loaderContext
137+
) {
117138
// Use `loaderContext.addContextDependency` to monitor the addition or removal of subdirectories in routesPath to trigger the rebuilding of virtual modules.
118139
// See more - https://webpack.js.org/api/loaders/#the-loader-context
119140
loaderContext.addContextDependency(routesPath);
@@ -128,7 +149,9 @@ export default value;`
128149
}
129150
},
130151
"code-from-file": {
131-
async source(loaderContext) {
152+
async source(
153+
/** @type {import("webpack").LoaderContext<unknown>} */ loaderContext
154+
) {
132155
const pathToFile = path.resolve(__dirname, "./code.js");
133156

134157
// Will trigger rebuild on changes in the file
@@ -138,6 +161,13 @@ export default value;`
138161

139162
return code;
140163
}
164+
},
165+
"src/components/button.js": "import { trim } from './utils';export const button = trim('button ');",
166+
"logo.svg": {
167+
type: ".svg",
168+
source() {
169+
return '<svg xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40"/></svg>';
170+
}
141171
}
142172
}),
143173
new webpack.experiments.schemes.VirtualUrlPlugin(
@@ -180,6 +210,8 @@ __webpack_require__.r(__webpack_exports__);
180210
/* harmony import */ var virtual_routes__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! virtual:routes */ 7);
181211
/* harmony import */ var virtual_code_from_file__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! virtual:code-from-file */ 8);
182212
/* harmony import */ var my_custom_scheme_my_module__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! my-custom-scheme:my-module */ 9);
213+
/* harmony import */ var virtual_src_components_button_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! virtual:src/components/button.js */ 10);
214+
/* harmony import */ var virtual_logo_svg__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! virtual:logo.svg */ 12);
183215

184216

185217

@@ -212,6 +244,16 @@ console.log(virtual_code_from_file__WEBPACK_IMPORTED_MODULE_7__.second); // Outp
212244

213245
console.log(my_custom_scheme_my_module__WEBPACK_IMPORTED_MODULE_8__["default"]); // Output `from virtual module with custom scheme`
214246

247+
// Import virtual module with custom context set in source function
248+
249+
250+
console.log(virtual_src_components_button_js__WEBPACK_IMPORTED_MODULE_9__.button); // Output `button`
251+
252+
// Import virtual asset (filename will have virtual: scheme removed)
253+
254+
255+
console.log(virtual_logo_svg__WEBPACK_IMPORTED_MODULE_10__); // Output path to logo.svg (without virtual: scheme)
256+
215257
__webpack_async_result__();
216258
} catch(e) { __webpack_async_result__(e); } }, 1);
217259

@@ -330,8 +372,8 @@ __webpack_require__.r(__webpack_exports__);
330372
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
331373
/* harmony export */ routes: () => (/* binding */ routes)
332374
/* harmony export */ });
333-
const routes = {a: () => __webpack_require__.e(/*! import() */ 1).then(__webpack_require__.bind(__webpack_require__, /*! ./routes/a.js */ 10)),
334-
b: () => __webpack_require__.e(/*! import() */ 2).then(__webpack_require__.bind(__webpack_require__, /*! ./routes/b.js */ 11))}
375+
const routes = {a: () => __webpack_require__.e(/*! import() */ 1).then(__webpack_require__.bind(__webpack_require__, /*! ./routes/a.js */ 13)),
376+
b: () => __webpack_require__.e(/*! import() */ 2).then(__webpack_require__.bind(__webpack_require__, /*! ./routes/b.js */ 14))}
335377

336378
/***/ }),
337379
/* 8 */
@@ -375,6 +417,54 @@ const msg = "from virtual module with custom scheme";
375417

376418
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (msg);
377419

420+
/***/ }),
421+
/* 10 */
422+
/*!****************************************!*\
423+
!*** virtual:src/components/button.js ***!
424+
\****************************************/
425+
/*! namespace exports */
426+
/*! export button [provided] [no usage info] [missing usage info prevents renaming] */
427+
/*! other exports [not provided] [no usage info] */
428+
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
429+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
430+
431+
__webpack_require__.r(__webpack_exports__);
432+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
433+
/* harmony export */ button: () => (/* binding */ button)
434+
/* harmony export */ });
435+
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils */ 11);
436+
const button = (0,_utils__WEBPACK_IMPORTED_MODULE_0__.trim)('button ');
437+
438+
/***/ }),
439+
/* 11 */
440+
/*!*********************************!*\
441+
!*** ./src/components/utils.js ***!
442+
\*********************************/
443+
/*! namespace exports */
444+
/*! export trim [provided] [no usage info] [missing usage info prevents renaming] */
445+
/*! other exports [not provided] [no usage info] */
446+
/*! runtime requirements: __webpack_require__.r, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
447+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
448+
449+
__webpack_require__.r(__webpack_exports__);
450+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
451+
/* harmony export */ trim: () => (/* binding */ trim)
452+
/* harmony export */ });
453+
const trim = (str) => str.trim();
454+
455+
/***/ }),
456+
/* 12 */
457+
/*!************************!*\
458+
!*** virtual:logo.svg ***!
459+
\************************/
460+
/*! default exports */
461+
/*! export default [not provided] [no usage info] [missing usage info prevents renaming] */
462+
/*! other exports [not provided] [no usage info] */
463+
/*! runtime requirements: __webpack_require__.p, module, __webpack_require__.* */
464+
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
465+
466+
module.exports = __webpack_require__.p + "logo.svg";
467+
378468
/***/ })
379469
/******/ ]);
380470
```
@@ -543,6 +633,11 @@ const msg = "from virtual module with custom scheme";
543633
/******/ };
544634
/******/ })();
545635
/******/
636+
/******/ /* webpack/runtime/publicPath */
637+
/******/ (() => {
638+
/******/ __webpack_require__.p = "dist/";
639+
/******/ })();
640+
/******/
546641
/******/ /* webpack/runtime/require chunk loading */
547642
/******/ (() => {
548643
/******/ // no baseURI
@@ -609,14 +704,15 @@ const msg = "from virtual module with custom scheme";
609704
## Unoptimized
610705

611706
```
612-
asset output.js 17.4 KiB [emitted] (name: main)
707+
asset output.js 20.2 KiB [emitted] (name: main)
613708
asset 1.output.js 803 bytes [emitted]
614709
asset 2.output.js 803 bytes [emitted]
615-
chunk (runtime: main) output.js (main) 1.66 KiB (javascript) 4.21 KiB (runtime) [entry] [rendered]
710+
asset logo.svg 78 bytes [emitted] [from: virtual:logo.svg] (auxiliary name: main)
711+
chunk (runtime: main) output.js (main) 2.15 KiB (javascript) 78 bytes (asset) 4.24 KiB (runtime) [entry] [rendered]
616712
> ./example.js main
617-
dependent modules 640 bytes [dependent] 9 modules
618-
runtime modules 4.21 KiB 7 modules
619-
./example.js 1.03 KiB [built] [code generated]
713+
dependent modules 791 bytes (javascript) 78 bytes (asset) [dependent] 12 modules
714+
runtime modules 4.24 KiB 8 modules
715+
./example.js 1.38 KiB [built] [code generated]
620716
[no exports]
621717
[used exports unknown]
622718
entry ./example.js main
@@ -638,9 +734,10 @@ webpack X.X.X compiled successfully
638734
## Production mode
639735

640736
```
641-
asset output.js 2.55 KiB [emitted] [minimized] (name: main)
737+
asset output.js 2.7 KiB [emitted] [minimized] (name: main)
642738
asset 263.output.js 118 bytes [emitted] [minimized]
643739
asset 722.output.js 118 bytes [emitted] [minimized]
740+
asset logo.svg 78 bytes [emitted] [from: virtual:logo.svg] (auxiliary name: main)
644741
chunk (runtime: main) 263.output.js 20 bytes [rendered]
645742
> ./routes/a.js virtual:routes 1:32-55
646743
./routes/a.js 20 bytes [built] [code generated]
@@ -651,11 +748,11 @@ chunk (runtime: main) 722.output.js 20 bytes [rendered]
651748
./routes/b.js 20 bytes [built] [code generated]
652749
[exports: default]
653750
import() ./routes/b.js virtual:routes 2:9-32
654-
chunk (runtime: main) output.js (main) 1.66 KiB (javascript) 4.21 KiB (runtime) [entry] [rendered]
751+
chunk (runtime: main) output.js (main) 2.15 KiB (javascript) 78 bytes (asset) 4.24 KiB (runtime) [entry] [rendered]
655752
> ./example.js main
656-
dependent modules 640 bytes [dependent] 9 modules
657-
runtime modules 4.21 KiB 7 modules
658-
./example.js 1.03 KiB [built] [code generated]
753+
dependent modules 791 bytes (javascript) 78 bytes (asset) [dependent] 11 modules
754+
runtime modules 4.24 KiB 8 modules
755+
./example.js 1.38 KiB [built] [code generated]
659756
[no exports]
660757
[no exports used]
661758
entry ./example.js main

examples/virtual-modules/example.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,13 @@ console.log(second); // Output `second`
2929
import message from "my-custom-scheme:my-module";
3030

3131
console.log(message); // Output `from virtual module with custom scheme`
32+
33+
// Import virtual module with custom context set in source function
34+
import { button } from "virtual:src/components/button.js";
35+
36+
console.log(button); // Output `button`
37+
38+
// Import virtual asset (filename will have virtual: scheme removed)
39+
import logoUrl from "virtual:logo.svg";
40+
41+
console.log(logoUrl); // Output path to logo.svg (without virtual: scheme)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const trim = (str) => str.trim();

0 commit comments

Comments
 (0)