Skip to content

Commit

Permalink
fix (labs/ssr): move to enhanced-resolve for package exports support (#…
Browse files Browse the repository at this point in the history
…3367)

The resolve package doesn't support package exports and various other
more modern resolution features. It seems `enhanced-resolve` (from
webpack) introduces this support.
  • Loading branch information
43081j committed Dec 2, 2022
1 parent f5065f5 commit b04c11b
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 22 deletions.
5 changes: 5 additions & 0 deletions .changeset/fuzzy-gorillas-wait.md
@@ -0,0 +1,5 @@
---
'@lit-labs/ssr': minor
---

Module resolution within SSR now supports package exports (via `package.json`)
42 changes: 38 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions packages/labs/ssr/package.json
Expand Up @@ -134,9 +134,9 @@
"@open-wc/testing-karma": "^4.0.9",
"@types/command-line-args": "^5.0.0",
"@types/koa": "^2.0.49",
"@types/koa__router": "^8.0.2",
"@types/koa-cors": "*",
"@types/koa-static": "^4.0.1",
"@types/koa__router": "^8.0.2",
"@types/parse5": "^6.0.1",
"@types/resolve": "^1.20.2",
"@webcomponents/template-shadowroot": "^0.1.0",
Expand All @@ -151,12 +151,12 @@
"@lit-labs/ssr-client": "^1.0.0",
"@lit/reactive-element": "^1.4.0",
"@types/node": "^16.0.0",
"enhanced-resolve": "^5.10.0",
"lit": "^2.3.0",
"lit-element": "^3.1.0",
"lit-html": "^2.3.0",
"node-fetch": "^3.2.8",
"parse5": "^6.0.1",
"resolve": "^1.10.1"
"parse5": "^6.0.1"
},
"engines": {
"node": ">=13.9.0"
Expand Down
24 changes: 9 additions & 15 deletions packages/labs/ssr/src/lib/module-loader.ts
Expand Up @@ -8,11 +8,9 @@ import * as path from 'path';
import {promises as fs} from 'fs';
import {URL, fileURLToPath, pathToFileURL} from 'url';
import * as vm from 'vm';
import resolveAsync from 'resolve';
import enhancedResolve from 'enhanced-resolve';
import {builtinModules} from 'module';

type PackageJSON = {main?: string; module?: string; 'jsnext:main'?: string};

const builtIns = new Set(builtinModules);

const specifierMatches = (specifier: string, match: string) =>
Expand Down Expand Up @@ -276,17 +274,11 @@ export const resolveSpecifier = async (
// a single version.
referrerPath = fileURLToPath(import.meta.url);
}
const modulePath = await resolve(specifier, {
basedir: path.dirname(referrerPath),
moduleDirectory: ['node_modules'],
const modulePath = await resolve(specifier, path.dirname(referrerPath), {
modules: ['node_modules'],
extensions: ['.js'],
// Some packages use a non-standard alternative to the "main" field
// in their package.json to differentiate their ES module version.
packageFilter: (packageJson: PackageJSON) => {
packageJson.main =
packageJson.module ?? packageJson['jsnext:main'] ?? packageJson.main;
return packageJson;
},
mainFields: ['module', 'jsnext:main', 'main'],
conditionNames: ['node'],
});
return pathToFileURL(modulePath);
}
Expand All @@ -301,10 +293,12 @@ const initializeImportMeta = (meta: {url: string}, module: vm.Module) => {

const resolve = async (
id: string,
opts: resolveAsync.AsyncOpts
path: string,
opts: Partial<enhancedResolve.ResolveOptions>
): Promise<string> => {
const resolver = enhancedResolve.create(opts);
return new Promise((res, rej) => {
resolveAsync(id, opts, (err, resolved) => {
resolver({}, path, id, {}, (err: unknown, resolved?: string) => {
if (err != null) {
rej(err);
} else {
Expand Down
34 changes: 34 additions & 0 deletions packages/labs/ssr/src/test/lib/module-loader_test.ts
Expand Up @@ -53,4 +53,38 @@ test('loads a module with a built-in import', async () => {
assert.ok(module.namespace.join);
});

test('resolves an exact exported path', async () => {
const loader = new ModuleLoader({global: window});
const result = await loader.importModule('./lit-import.js', testIndex);
const {module, path: modulePath} = result;
assert.is(module.namespace.litIsServer, true);
assert.ok(loader.cache.has(modulePath));
const isServerPath = path.resolve(
path.dirname(testIndex),
'../../../../../lit-html/node/is-server.js'
);
assert.ok(loader.cache.has(isServerPath));
});

test('resolves a root exported path (.)', async () => {
const loader = new ModuleLoader({global: window});
const result = await loader.importModule(
'./lit-import-from-root.js',
testIndex
);
const {module, path: modulePath} = result;
assert.is(module.namespace.litIsServer, true);
assert.ok(loader.cache.has(modulePath));
const litPath = path.resolve(
path.dirname(testIndex),
'../../../../../lit/index.js'
);
const isServerPath = path.resolve(
path.dirname(testIndex),
'../../../../../lit-html/node/is-server.js'
);
assert.ok(loader.cache.has(litPath));
assert.ok(loader.cache.has(isServerPath));
});

test.run();
@@ -0,0 +1,2 @@
import {isServer} from 'lit';
export const litIsServer = isServer;
@@ -0,0 +1,2 @@
import {isServer} from 'lit-html/is-server.js';
export const litIsServer = isServer;

0 comments on commit b04c11b

Please sign in to comment.