Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Index.html can not be omitted when serving multiple files #1315

Closed
tamuraryoya opened this issue May 7, 2018 · 16 comments 路 Fixed by #3996
Closed

Index.html can not be omitted when serving multiple files #1315

tamuraryoya opened this issue May 7, 2018 · 16 comments 路 Fixed by #3996

Comments

@tamuraryoya
Copy link

馃悰 bug report

When bundling and serve multiple entry files, / index.html can not be accessed with localhost:1234/

However, you can access it with localhost: 1234 / index.html

馃帥 Configuration (.babelrc, package.json, cli command)

//- src/index.pug
h1 hello world!
//- src/sub.pug
h1 sub page!
$ parcel 'src/**/*.pug'

馃 Expected Behavior

When accessing localhost:1234/, "hello world!" is displayed

馃槸 Current Behavior

Accessing localhost:1234/ will display empty HTML

<html>
  <head></head>
  <body></body>
</html>

However, accessing localhost: 1234 / index.html will display the page correctly

馃拋 Possible Solution

I do not know, but when accessed with / we have to make sure to check the existence of / index.html

馃實 Your Environment

Software Version(s)
Parcel v1.8.1
Node v8.11.1
npm/Yarn v6.0.0/v1.5.1
Operating System MacBook Pro (High Sierra)
@DeMoorJasper
Copy link
Member

DeMoorJasper commented May 7, 2018

This is because it currently checks for an entrypoint and multiple entrypoints works with a html entrypoint thats being created in the background as a main asset to link all assets to.

This is an empty file and therefore it shows you that file as mainasset

Sent with GitHawk

@tamuraryoya
Copy link
Author

Thank you!

This was a specification
Will this be fixed?

@DeMoorJasper DeMoorJasper changed the title Index.html can not be omitted when serveing multiple files Index.html can not be omitted when serving multiple files May 12, 2018
@lucaseverett
Copy link

It would be helpful to have index.html served from / and any other entry points served without .html.

So, page1.html would be resolved by visiting /page1.

Is there a way to create URL rewrites for the server locally in a project?

@DeMoorJasper
Copy link
Member

@lucaseverett This is unrelated to the issue, but I'm fairly sure there is already an issue concerning this. It's currently not possible, feel free to open a PR to implement this, it should be fairly easy to do this

@MathieuLoutre
Copy link

I've got a working solution for this (as explained in #1778) and can PR if this is agreeable.

Essentially, it enhances the respond method by looking for indexes (with a method replacing sendIndex called findIndex), looking for the main bundle as it does now, failing that looking for an HTML file called index.html.

 function respond() {
      let {pathname} = url.parse(req.url);
      if (bundler.error) {
        return send500(bundler.error);
      } else if (
        !pathname.startsWith(bundler.options.publicURL) ||
        path.extname(pathname) === ''
      ) {
        const index = findIndex(pathname)
        if (index) {
          req.url = `/${path.basename(index)}`;
          serve(req, res, send404);
        }
        else {
          send404();
        }
      } else {
        // Otherwise, serve the file from the dist folder
        req.url = pathname.slice(bundler.options.publicURL.length);
        return serve(req, res, send404);
      }
    }

    function findIndex(pathname) {
     // If the bundle is HTML, send that
      if (bundler.mainBundle.type === 'html') {
        return bundler.mainBundle.name;
      }
      else if (pathname === bundler.options.publicURL) {
        // if the pathname is empty, look for files named index.html in the bundle and send back the first one. If there's nothing, return null;
        const indexes = Array.from(bundler.mainBundle.childBundles).filter((asset) => path.basename(asset.name) === 'index.html');
        return indexes[0].name;
      }
      return null;
    }

@pbastowski
Copy link

pbastowski commented Sep 30, 2018

Has there been any progress on this issue? It is a very useful feature.

@LuudJanssen
Copy link

Started working on a pull request for this issue

I'm experiencing some test errors, which I asked about on Spectrum. Once those are resolved I can add the pull request. It is using @MathieuLoutre's fix (here) and not setting index to true as suggested here if that would be the better option I can change that in the PR, the tests for it stay the same.

@ideoclickVanessa
Copy link

FWIW: This issue also occurs when you just have a single .tsx entry point (parcel src/index.tsx) as well

@bichotll
Copy link

Same happened here when parcel *.html.

That actually confused my colleague and thought the computer was under the weather lol
It would be nice to solve this issue. It would avoid any confusion in the future.

@aldovincenti
Copy link

Is there any news on this issue?

@mismith
Copy link

mismith commented Jul 2, 2019

Looks like lots of people requesting this feature, any word on whether there's even a workaround to solve this?

@elisei-timofte
Copy link

Same here. Any updates?

@shaunakv1
Copy link

Same here, just ran into this, with the whole team confused as to what happened, when the second entry point was first added.

@bgschiller
Copy link

bgschiller commented Aug 21, 2019

In the meantime, I have this workaround set up:

// run-parcel.js
const Bundler = require('parcel-bundler');
const express = require('express');

const bundler = new Bundler(['src/index.html', 'src/login.html', 'src/logout.html']);
const app = express();

app.get('/', (req, res, next) => {
  req.url = '/index.html';
  app._router.handle(req, res, next);
});

app.use(bundler.middleware());

const port = Number(process.env.PORT || 1234);
app.listen(port);
console.log(`listening at http://localhost:${port}`);

then run node run-parcel.js instead of parcel src/*.html.

@hanabi1224
Copy link
Contributor

Looking forward to this feature!

@johnagan
Copy link

johnagan commented Jul 28, 2020

I ended up writing a local plugin as a bandaid, until we get a legit fix. It uses the same modules included in Parcel v1. Only gotcha is you have to use the watch command to trigger it. Here's an example of what it looks like - ymmv:

Running

parcel watch [entries] --serve
parcel watch [entries] --serve --open

Plugin Code

const serveStatic = require("serve-static"); // included in parcel v1
const { createServer } = require("http");

module.exports = (bundler) => {
  let server = null; // prevent from restarting on rebundle
  const openBrowser = process.argv.includes("--open");
  const useServer = process.argv.includes("--serve");

  bundler.on("bundled", () => {
    if (useServer && !server && bundler.options.watch) {      
      server = startServer(bundler.options.outDir, 8080, openBrowser);
    }
  });
}

function startServer(outDir, port, openBrowser) {
  const serve = serveStatic(outDir, { extensions: ["html"] });

  // 404 handler
  const redirect = (res) => {
    res.writeHead(302, { Location: "/404" });
    res.end();
  };

  // request handler
  const handler = (req, res) => {
    serve(req, res, () => redirect(res));
  };

  // start server
  return createServer(handler).listen(port, () => {
    // optional if you want to open the browser (included in parcel v1)
    if (openBrowser) require("opn")(`http://localhost:${port}`);
  });
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.