Skip to content

Commit

Permalink
Improve server index file matching (#8957)
Browse files Browse the repository at this point in the history
  • Loading branch information
mischnic authored May 12, 2023
1 parent 482d23a commit 0b3d798
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 49 deletions.
24 changes: 16 additions & 8 deletions packages/core/integration-tests/test/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,33 +36,41 @@ describe('html', function () {
assets: ['index.html'],
},
{
// index.html
name: 'index.html',
assets: ['index.html'],
},
{
// foo/index.html
name: 'index.html',
assets: ['index.html'],
},
{
type: 'png',
assets: ['100x100.png'],
// other.html
name: 'other.html',
assets: ['other.html'],
},
{
type: 'svg',
assets: ['icons.svg'],
// foo/other.html
name: 'other.html',
assets: ['other.html'],
},
{
type: 'css',
assets: ['index.css'],
type: 'svg',
assets: ['icons.svg'],
},
{
type: 'html',
assets: ['other.html'],
type: 'png',
assets: ['100x100.png'],
},
{
type: 'js',
assets: ['index.js'],
},
{
type: 'css',
assets: ['index.css'],
},
]);

let files = await outputFS.readdir(distDir);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Other foo page</title>
</head>
<body>
<div>Some other foo page...</div>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@

<body>
<h1>Hello world</h1>
<p>Linking to <a href="other.html">another page</a> and <a href="foo/index.html">another page</a></p>
<p>
Linking to <a href="other.html">another page</a> and <a href="foo/index.html">another page</a>
and <a href="foo/other.html">another page</a>
</p>
<a href="#hash_link">Hash link</a>
<a href="mailto:[email protected]">Mailto link</a>
<a href="tel:+33636757575">Tel link</a>
Expand Down
62 changes: 34 additions & 28 deletions packages/core/integration-tests/test/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,48 +141,48 @@ describe('server', function () {

it('should serve a default page if the main bundle is an HTML asset', async function () {
let port = await getPort();
let b = bundler(
[
path.join(__dirname, '/integration/html/other.html'),
path.join(__dirname, '/integration/html/index.html'),
],
{
defaultTargetOptions: {
distDir,
},
config,
serveOptions: {
https: false,
port: port,
host: 'localhost',
},
let b = bundler(path.join(__dirname, '/integration/html/index.html'), {
defaultTargetOptions: {
distDir,
},
);
config,
serveOptions: {
https: false,
port: port,
host: 'localhost',
},
});

subscription = await b.watch();
await getNextBuild(b);

let rootIndexFile = await outputFS.readFile(
let rootIndex = await outputFS.readFile(
path.join(distDir, 'index.html'),
'utf8',
);

let data = await get('/', port);
assert.equal(data, rootIndexFile);

let fooIndexFile = await outputFS.readFile(
let other = await outputFS.readFile(
path.join(distDir, 'other.html'),
'utf8',
);
let fooIndex = await outputFS.readFile(
path.join(distDir, 'foo/index.html'),
'utf8',
);
let fooOther = await outputFS.readFile(
path.join(distDir, 'foo/other.html'),
'utf8',
);

data = await get('/foo', port);
assert.equal(data, fooIndexFile);

data = await get('/foo/bar', port);
assert.equal(data, fooIndexFile);
assert.equal(await get('/', port), rootIndex);
assert.equal(await get('/something', port), rootIndex);
assert.equal(await get('/other', port), other);
assert.equal(await get('/foo', port), rootIndex);
assert.equal(await get('/foo/', port), fooIndex);
assert.equal(await get('/foo/bar', port), fooIndex);
assert.equal(await get('/foo/other', port), fooOther);
});

it('should serve a default page if the main bundle is an HTML asset even if it is not called index', async function () {
it('should serve a default page if the single HTML bundle is not called index', async function () {
let port = await getPort();
let inputPath = path.join(__dirname, '/integration/html/other.html');
let b = bundler(inputPath, {
Expand Down Expand Up @@ -499,6 +499,12 @@ describe('server', function () {
assets: ['index.html'],
},
{
// other.html
name: 'other.html',
assets: ['other.html'],
},
{
// foo/other.html
name: 'other.html',
assets: ['other.html'],
},
Expand Down
46 changes: 34 additions & 12 deletions packages/reporters/dev-server/src/Server.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export function setHeaders(res: Response) {
res.setHeader('Cache-Control', 'max-age=0, must-revalidate');
}

const SLASH_REGEX = /\//g;

export const SOURCES_ENDPOINT = '/__parcel_source_root';
const EDITOR_ENDPOINT = '/__parcel_launch_editor';
const TEMPLATE_404 = fs.readFileSync(
Expand Down Expand Up @@ -197,18 +199,38 @@ export default class Server {
if (htmlBundleFilePaths.length === 1) {
indexFilePath = htmlBundleFilePaths[0];
} else {
indexFilePath = htmlBundleFilePaths
.filter(v => {
let dir = path.posix.dirname(v);
let withoutExtension = path.posix.basename(
v,
path.posix.extname(v),
);
return withoutExtension === 'index' && req.url.startsWith(dir);
})
.sort((a, b) => {
return b.length - a.length;
})[0];
let bestMatch = null;
for (let bundle of htmlBundleFilePaths) {
let bundleDir = path.posix.dirname(bundle);
let bundleDirSubdir = bundleDir === '/' ? bundleDir : bundleDir + '/';
let withoutExtension = path.posix.basename(
bundle,
path.posix.extname(bundle),
);
let isIndex = withoutExtension === 'index';

let matchesIsIndex = null;
if (isIndex && req.url.startsWith(bundleDirSubdir)) {
// bundle is /bar/index.html and something inside of /bar/** was requested
matchesIsIndex = true;
} else if (req.url == path.posix.join(bundleDir, withoutExtension)) {
// bundle is /bar/foo.html and /bar/foo was requested
matchesIsIndex = false;
}
if (matchesIsIndex != null) {
let depth = bundle.match(SLASH_REGEX)?.length ?? 0;
if (
bestMatch == null ||
// This one is more specific (deeper)
bestMatch.depth < depth ||
// This one is just as deep, but the bundle name matches and not just index.html
(bestMatch.depth === depth && bestMatch.isIndex)
) {
bestMatch = {bundle, depth, isIndex: matchesIsIndex};
}
}
}
indexFilePath = bestMatch?.['bundle'] ?? htmlBundleFilePaths[0];
}

if (indexFilePath) {
Expand Down

0 comments on commit 0b3d798

Please sign in to comment.