@@ -116,6 +116,7 @@ The configuration currently reads the following top-level fields:
116116 "disableExperimentalSEAWarning" : true , // Default: false
117117 "useSnapshot" : false , // Default: false
118118 "useCodeCache" : true , // Default: false
119+ "useVfs" : true , // Default: false
119120 "execArgv" : [" --no-warnings" , " --max-old-space-size=4096" ], // Optional
120121 "execArgvExtension" : " env" , // Default: "env", options: "none", "env", "cli"
121122 "assets" : { // Optional
@@ -175,6 +176,86 @@ const raw = getRawAsset('a.jpg');
175176See documentation of the [ ` sea.getAsset() ` ] [ ] , [ ` sea.getAssetAsBlob() ` ] [ ] ,
176177[ ` sea.getRawAsset() ` ] [ ] and [ ` sea.getAssetKeys() ` ] [ ] APIs for more information.
177178
179+ ### Virtual file system (VFS) for assets
180+
181+ <!-- YAML
182+ added: REPLACEME
183+ -->
184+
185+ > Stability: 1 - Experimental
186+
187+ In addition to using the ` node:sea ` API to access individual assets, the
188+ bundled assets can be exposed as a read-only [ virtual file system] [ ] and
189+ accessed through standard ` node:fs ` APIs. To enable this, set
190+ ` "useVfs": true ` in the SEA configuration.
191+
192+ A virtual file system never shadows the real file system: it is mounted at a
193+ reserved mount point that cannot exist on the real file system, and the mount
194+ point is chosen at runtime rather than being a fixed path. When ` useVfs ` is
195+ enabled, the injected main script itself is placed at the root of the mount
196+ and executed from there, so ` __filename ` and ` __dirname ` point inside the
197+ virtual file system instead of reflecting [ ` process.execPath ` ] [ ] . Bundled
198+ code therefore reaches the assets through ` __dirname ` -relative paths and
199+ relative [ ` require() ` ] [ ] calls, without having to know the mount point:
200+
201+ ``` cjs
202+ const fs = require (' node:fs' );
203+ const path = require (' node:path' );
204+
205+ // __dirname is the root of the virtual file system holding the assets.
206+ const rawConfig = fs .readFileSync (path .join (__dirname , ' config.json' ), ' utf8' );
207+ const data = fs .readFileSync (path .join (__dirname , ' data/file.txt' ));
208+
209+ // Directory operations work too.
210+ const files = fs .readdirSync (path .join (__dirname , ' assets' ));
211+
212+ // Check if a bundled file exists.
213+ if (fs .existsSync (path .join (__dirname , ' optional.json' ))) {
214+ // ...
215+ }
216+ ```
217+
218+ The VFS supports the ` node:fs ` operations for reading files and directories.
219+ Since the SEA VFS is read-only, write operations fail with ` EROFS ` . See the
220+ [ VFS documentation] [ ] for the full list of supported operations.
221+
222+ #### Loading modules from the VFS in a SEA
223+
224+ When ` useVfs ` is enabled, the main script is executed from inside the
225+ virtual file system, and ` require() ` uses the [ module loader
226+ integration] [ ] of the VFS to load modules from the bundled assets. This
227+ supports relative requires (e.g. ` require('./helper.js') ` ) as well as
228+ ` node_modules ` package lookups, which are confined to the mount:
229+
230+ ``` cjs
231+ // Require bundled modules using relative paths.
232+ const myModule = require (' ./lib/mymodule.js' );
233+
234+ // Packages bundled under the node_modules asset prefix also resolve.
235+ const dep = require (' some-package' );
236+ ```
237+
238+ #### ESM limitations
239+
240+ The ` useVfs ` option does not currently support ESM entry points. Using
241+ ` "useVfs": true ` together with ` "mainFormat": "module" ` is not supported.
242+ The main script must use CommonJS (` require() ` ) when VFS is enabled.
243+
244+ #### Snapshot and code caching limitations
245+
246+ ` "useVfs": true ` cannot be used together with ` "useSnapshot": true ` or
247+ ` "useCodeCache": true ` . The code cache limitation is due to incomplete
248+ implementation, not a technical impossibility. Consider bundling the
249+ application if startup performance matters and do not rely on module loading
250+ from the VFS in that case.
251+
252+ #### Native addon limitations
253+
254+ Native addons (` .node ` files) cannot be loaded directly from the VFS because
255+ ` process.dlopen() ` requires files on the real file system. To use native
256+ addons in a SEA with VFS, write the asset to a temporary file first. See
257+ [ Using native addons in the injected main script] [ ] for an example.
258+
178259### Startup snapshot support
179260
180261The ` useSnapshot ` field can be used to enable startup snapshot support. In this
@@ -648,6 +729,8 @@ to help us document them.
648729[Generating single executable preparation blobs]: # 1-generating-single-executable-preparation-blobs
649730[Mach-O]: https://en.wikipedia.org/wiki/Mach-O
650731[PE]: https://en.wikipedia.org/wiki/Portable_Executable
732+ [Using native addons in the injected main script]: # using-native-addons-in-the-injected-main-script
733+ [VFS documentation]: vfs.md
651734[Windows SDK]: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/
652735[` process.execPath` ]: process.md#processexecpath
653736[` require()` ]: modules.md#requireid
@@ -660,8 +743,10 @@ to help us document them.
660743[` v8.startupSnapshot` API]: v8.md#startup-snapshot-api
661744[documentation about startup snapshot support in Node.js]: cli.md#--build-snapshot
662745[fuse]: https://www.electronjs.org/docs/latest/tutorial/fuses
746+ [module loader integration]: vfs.md#module-loader-integration
663747[postject]: https://github.com/nodejs/postject
664748[postject-linux-arm64-issue]: https://github.com/nodejs/postject/issues/105
665749[signtool]: https://learn.microsoft.com/en-us/windows/win32/seccrypto/signtool
666750[single executable applications]: https://github.com/nodejs/single-executable
667751[supported by Node.js]: https://github.com/nodejs/node/blob/main/BUILDING.md#platform-list
752+ [virtual file system]: vfs.md
0 commit comments