Skip to content

Commit

Permalink
add support for cross-mount imports (#1355)
Browse files Browse the repository at this point in the history
  • Loading branch information
FredKSchott authored Oct 18, 2020
1 parent 1a197fb commit 07a1216
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 28 deletions.
15 changes: 8 additions & 7 deletions snowpack/src/build/import-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'path';
import url from 'url';
import {ImportMap, SnowpackConfig} from '../types/snowpack';
import {findMatchingAliasEntry, getExt, relativeURL, replaceExt} from '../util';
import {defaultFileExtensionMapping} from './file-urls';
import {defaultFileExtensionMapping, getUrlForFile} from './file-urls';

const cwd = process.cwd();

Expand All @@ -14,8 +14,7 @@ interface ImportResolverOptions {
}

/** Perform a file disk lookup for the requested import specifier. */
export function getImportStats(dirLoc: string, spec: string): fs.Stats | false {
const importedFileOnDisk = path.resolve(dirLoc, spec);
export function getImportStats(importedFileOnDisk: string): fs.Stats | false {
try {
return fs.statSync(importedFileOnDisk);
} catch (err) {
Expand Down Expand Up @@ -66,18 +65,20 @@ export function createImportResolver({
}

if (spec.startsWith('/')) {
const importStats = getImportStats(cwd, spec.substr(1));
const importStats = getImportStats(path.resolve(cwd, spec.substr(1)));
return resolveSourceSpecifier(spec, importStats, config);
}
if (spec.startsWith('./') || spec.startsWith('../')) {
const importStats = getImportStats(path.dirname(fileLoc), spec);
return resolveSourceSpecifier(spec, importStats, config);
const importedFileLoc = path.resolve(path.dirname(fileLoc), spec);
const importStats = getImportStats(importedFileLoc);
const newSpec = getUrlForFile(importedFileLoc, config) || spec;
return resolveSourceSpecifier(newSpec, importStats, config);
}
const aliasEntry = findMatchingAliasEntry(config, spec);
if (aliasEntry && aliasEntry.type === 'path') {
const {from, to} = aliasEntry;
let result = spec.replace(from, to);
const importStats = getImportStats(cwd, result);
const importStats = getImportStats(path.resolve(cwd, result));
result = resolveSourceSpecifier(result, importStats, config);
// replace Windows backslashes at the end, after resolution
result = relativeURL(path.dirname(fileLoc), result);
Expand Down
51 changes: 33 additions & 18 deletions snowpack/src/commands/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import {
openInBrowser,
parsePackageImportSpecifier,
readFile,
relativeURL,
replaceExt,
resolveDependencyManifest,
updateLockfileHash,
Expand Down Expand Up @@ -795,26 +796,40 @@ export async function startServer(commandOptions: CommandOptions): Promise<Serve
},
(spec) => {
// Try to resolve the specifier to a known URL in the project
const resolvedImportUrl = resolveImportSpecifier(spec);
if (resolvedImportUrl) {
// Ignore "http://*" imports
if (url.parse(resolvedImportUrl).protocol) {
return resolvedImportUrl;
}
// Support proxy file imports
const extName = path.extname(resolvedImportUrl);
if (
extName &&
(responseExt === '.js' || responseExt === '.html') &&
extName !== '.js'
) {
return resolvedImportUrl + '.proxy.js';
}
return resolvedImportUrl;
let resolvedImportUrl = resolveImportSpecifier(spec);
// Handle an import that couldn't be resolved
if (!resolvedImportUrl) {
missingPackages.push(spec);
return spec;
}
// Ignore "http://*" imports
if (url.parse(resolvedImportUrl).protocol) {
return spec;
}
// Ignore packages marked as external
if (config.installOptions.externalPackage?.includes(resolvedImportUrl)) {
return spec;
}
// Handle normal "./" & "../" import specifiers
const importExtName = path.posix.extname(resolvedImportUrl);
const isProxyImport =
importExtName &&
(responseExt === '.js' || responseExt === '.html') &&
importExtName !== '.js';
const isAbsoluteUrlPath = path.posix.isAbsolute(resolvedImportUrl);
if (isProxyImport) {
resolvedImportUrl = resolvedImportUrl + '.proxy.js';
}

missingPackages.push(spec);
return spec;
// When dealing with an absolute import path, we need to honor the baseUrl
if (isAbsoluteUrlPath) {
resolvedImportUrl = relativeURL(path.posix.dirname(reqPath), resolvedImportUrl);
}
// Make sure that a relative URL always starts with "./"
if (!resolvedImportUrl.startsWith('.') && !resolvedImportUrl.startsWith('/')) {
resolvedImportUrl = './' + resolvedImportUrl;
}
return resolvedImportUrl;
},
);

Expand Down
2 changes: 1 addition & 1 deletion test-dev/__snapshots__/dev.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ exports[`snowpack dev smoke: js 1`] = `
* When you're ready to start on your site, clear the file. Happy hacking!
**/
import confetti from '/web_modules/canvas-confetti.js';
import confetti from '../web_modules/canvas-confetti.js';
confetti.create(document.getElementById('canvas'), {
resize: true,
Expand Down
2 changes: 1 addition & 1 deletion test/build/config-mount/__snapshots__
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Array [
]
`;

exports[`snowpack build config-mount: build/__snowpack__/env.js 1`] = `"export default {\\"MODE\\":\\"production\\",\\"NODE_ENV\\":\\"production\\"};"`;
exports[`snowpack build config-mount: build/__snowpack__/env.js 1`] = `"export default {\\"MODE\\":\\"production\\",\\"NODE_ENV\\":\\"production\\",\\"SSR\\":false};"`;

exports[`snowpack build config-mount: build/a/index.js 1`] = `"console.log('a');"`;

Expand Down
12 changes: 11 additions & 1 deletion test/build/resolve-imports/__snapshots__
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Array [
"_dist_/index.js",
"_dist_/sort.js",
"_dist_/test-mjs.js",
"robots.txt",
"robots.txt.proxy.js",
"TEST_WMU/@css/package-b/style.css",
"TEST_WMU/@css/package-b/style.css.proxy.js",
"TEST_WMU/@fortawesome/fontawesome-free/svgs/solid/ad.svg",
Expand Down Expand Up @@ -94,6 +96,9 @@ exports[`snowpack build resolve-imports: build/_dist_/index.html 1`] = `
import styles from './components/style.css.proxy.js'; // relative import
import styles_ from './components/style.css.proxy.js'; // relative import
console.log(styles, styles_);
// Importing across mounted directories
import robotsTxtRef from '../robots.txt.proxy.js';
console.log(robotsTxtRef);
</script>
<!-- exception test 1: comments should be ignored -->
<!-- <script type=\\"module\\" src=\\"preact\\"></script> -->
Expand Down Expand Up @@ -148,7 +153,10 @@ import styles from './components/style.css.proxy.js'; // relative import
import styles_ from './components/style.css.proxy.js'; // relative import
console.log(styles, styles_);
import adSvg from '../TEST_WMU/@fortawesome/fontawesome-free/svgs/solid/ad.svg.proxy.js';
console.log(adSvg);"
console.log(adSvg);
// Importing across mounted directories
import robotsTxtRef from '../robots.txt.proxy.js';
console.log(robotsTxtRef);"
`;

exports[`snowpack build resolve-imports: build/_dist_/sort.js 1`] = `"export default (arr) => arr.sort();"`;
Expand Down Expand Up @@ -233,3 +241,5 @@ exports[`snowpack build resolve-imports: build/TEST_WMU/import-map.json 1`] = `
}
}"
`;

exports[`snowpack build resolve-imports: build/robots.txt.proxy.js 1`] = `"export default \\"/robots.txt\\";"`;
1 change: 1 addition & 0 deletions test/build/resolve-imports/public/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
THIS IS A ROBOTS.TXT TEST FILE
1 change: 1 addition & 0 deletions test/build/resolve-imports/snowpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module.exports = {
},
mount: {
'./src': '/_dist_',
'./public': '/',
},
devOptions: {
fallback: '_dist_/index.html',
Expand Down
4 changes: 4 additions & 0 deletions test/build/resolve-imports/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
import styles from './components/style.css'; // relative import
import styles_ from '@app/components/style.css'; // relative import
console.log(styles, styles_);

// Importing across mounted directories
import robotsTxtRef from '../public/robots.txt';
console.log(robotsTxtRef);
</script>

<!-- exception test 1: comments should be ignored -->
Expand Down
4 changes: 4 additions & 0 deletions test/build/resolve-imports/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,7 @@ console.log(styles, styles_);

import adSvg from '@fortawesome/fontawesome-free/svgs/solid/ad.svg';
console.log(adSvg);

// Importing across mounted directories
import robotsTxtRef from '../public/robots.txt';
console.log(robotsTxtRef);

1 comment on commit 07a1216

@vercel
Copy link

@vercel vercel bot commented on 07a1216 Oct 18, 2020

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.