diff --git a/snowpack/assets/require-or-import.js b/snowpack/assets/require-or-import.js index ffdcaf7be1..686b6e7e52 100644 --- a/snowpack/assets/require-or-import.js +++ b/snowpack/assets/require-or-import.js @@ -10,6 +10,10 @@ const r = require('resolve'); */ module.exports = async function requireOrImport(filepath, { from = process.cwd() } = {}) { return new Promise((resolve, reject) => { + if(filepath.startsWith('node:')) { + return NATIVE_IMPORT(filepath).then(mdl => resolve(mdl), err => reject(err)); + } + // Resolve path based on `from` const resolvedPath = r.sync(filepath, { basedir: from diff --git a/snowpack/src/ssr-loader/index.ts b/snowpack/src/ssr-loader/index.ts index db7c7ae5a7..8c9ff789e6 100644 --- a/snowpack/src/ssr-loader/index.ts +++ b/snowpack/src/ssr-loader/index.ts @@ -1,6 +1,6 @@ import {existsSync, readFileSync} from 'fs'; -import {resolve} from 'url'; -import {ServerRuntime, ServerRuntimeConfig} from '../types'; +import {resolve, pathToFileURL} from 'url'; +import {ServerRuntime, ServerRuntimeConfig, LoadResult} from '../types'; import {sourcemap_stacktrace} from './sourcemaps'; import {transform} from './transform'; import {REQUIRE_OR_IMPORT} from '../util'; @@ -57,11 +57,12 @@ export function createLoader({config, load}: ServerRuntimeConfig): ServerRuntime return promise; } - async function initializeModule(url: string, loaded: {contents: string}, urlStack: string[]) { + async function initializeModule(url: string, loaded: LoadResult, urlStack: string[]) { const {code, deps, css, names} = transform(loaded.contents); const exports = {}; const allCss = new Set(css.map((relative) => resolve(url, relative))); + const fileURL = loaded.originalFileLoc ? pathToFileURL(loaded.originalFileLoc) : null; const args = [ { @@ -101,7 +102,7 @@ export function createLoader({config, load}: ServerRuntimeConfig): ServerRuntime }, { name: names.__import_meta, - value: {url}, + value: {url: fileURL}, }, ...(await Promise.all( diff --git a/snowpack/src/types.ts b/snowpack/src/types.ts index c2e902507b..6001b69a48 100644 --- a/snowpack/src/types.ts +++ b/snowpack/src/types.ts @@ -27,7 +27,7 @@ export type DeepPartial = { export interface ServerRuntimeConfig { config: SnowpackConfig; - load: (url: string) => Promise<{contents: string}>; + load: (url: string) => Promise>; } export interface ServerRuntime { importModule: (url: string) => Promise>; diff --git a/test/create-snowpack-app/__snapshots__/create-snowpack-app.test.js.snap b/test/create-snowpack-app/__snapshots__/create-snowpack-app.test.js.snap index 9ec66990b6..87d538cafc 100644 --- a/test/create-snowpack-app/__snapshots__/create-snowpack-app.test.js.snap +++ b/test/create-snowpack-app/__snapshots__/create-snowpack-app.test.js.snap @@ -631,7 +631,7 @@ a { `; exports[`create-snowpack-app app-template-blank > build: dist/index.js 1`] = ` -"const counter = document.querySelector(\\"#counter\\") +"const counter = document.querySelector('#counter'); let seconds = 0; setInterval(() => { seconds += 1; diff --git a/test/snowpack/runtime/runtime.test.js b/test/snowpack/runtime/runtime.test.js index 2325b7ed60..0c74432fcc 100644 --- a/test/snowpack/runtime/runtime.test.js +++ b/test/snowpack/runtime/runtime.test.js @@ -47,4 +47,47 @@ describe('runtime', () => { await fixture.cleanup(); } }); + + // This test is skipped due to the way Jest runs tests, you can't use dynamic import + // which this test depends on. See: + // https://github.com/nodejs/node/issues/35889 + it.skip('Provides import.meta.fileURL in SSR', async () => { + const fixture = await testRuntimeFixture({ + 'main.js': dedent` + import fs from 'node:fs/promises'; + + const url = new URL('./data.json', import.meta.url); + + export async function getData() { + const json = await fs.readFile(url, 'utf-8'); + const data = JSON.parse(json); + return data; + } + `, + 'data.json': dedent` + [ 1, 2 ] + `, + 'package.json': dedent` + { + "version": "1.0.1", + "name": "@snowpack/test-runtime-invalidate" + } + `, + 'snowpack.config.json': dedent` + { + "packageOptions": { + "external": ["node:fs/promises"] + } + } + ` + }); + + try { + let mod = await fixture.runtime.importModule('/main.js'); + + expect(await mod.exports.getData()).toStrictEqual([1, 2]); + } finally { + await fixture.cleanup(); + } + }); });