Skip to content

Commit

Permalink
Make import.meta.url be the file URL in SSR (#3472)
Browse files Browse the repository at this point in the history
* Make import.meta.url be the file URL in SSR

This fixes SSR which previously was the mounted path to the file (just the path, so not a valid URL). It is now the actual file as a URL. This allows you to do relative lookups.

This also adds support for importing via the `node:` prefix.

* Update the snapshot
  • Loading branch information
matthewp committed Jun 22, 2021
1 parent 2590b55 commit 8cff033
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 6 deletions.
4 changes: 4 additions & 0 deletions snowpack/assets/require-or-import.js
Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions 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';
Expand Down Expand Up @@ -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<string>, 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 = [
{
Expand Down Expand Up @@ -101,7 +102,7 @@ export function createLoader({config, load}: ServerRuntimeConfig): ServerRuntime
},
{
name: names.__import_meta,
value: {url},
value: {url: fileURL},
},

...(await Promise.all(
Expand Down
2 changes: 1 addition & 1 deletion snowpack/src/types.ts
Expand Up @@ -27,7 +27,7 @@ export type DeepPartial<T> = {

export interface ServerRuntimeConfig {
config: SnowpackConfig;
load: (url: string) => Promise<{contents: string}>;
load: (url: string) => Promise<LoadResult<string>>;
}
export interface ServerRuntime {
importModule: <T = any>(url: string) => Promise<ServerRuntimeModule<T>>;
Expand Down
Expand Up @@ -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;
Expand Down
43 changes: 43 additions & 0 deletions test/snowpack/runtime/runtime.test.js
Expand Up @@ -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();
}
});
});

1 comment on commit 8cff033

@vercel
Copy link

@vercel vercel bot commented on 8cff033 Jun 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.