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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rollup-plugin-html-module #2932

Closed
Crisfole opened this issue Jun 12, 2019 · 5 comments
Closed

rollup-plugin-html-module #2932

Crisfole opened this issue Jun 12, 2019 · 5 comments

Comments

@Crisfole
Copy link

Feature Use Case

I'd love if there was officially supported html module support that handled dependencies correctly.

Feature Proposal

If I import (or use as an entry) an html file, I want rollup to find all the relevant dependencies (see: Parcel's HtmlAsset.js), and emit a chunk for each dependency (replacing the url as appropriate).

If this is the wrong place to ask for an official plugin feel free to close.

@lukastaegert
Copy link
Member

Sounds like a duplicate of #2873, at least concerning html entry points. Import of html will only be supported in Rollup core if it becomes a core JavaScript language feature, so probably not. Everything should be there to write a plugin to do what you intend (and I agree this would be a very useful plugin!), if not, let me know.

@lukastaegert
Copy link
Member

Thing is, I am stretched to the limit regarding my capacity, so I would hope someone else would pick this up. Maybe someone like @surma already has something up their sleeve?

@Crisfole
Copy link
Author

I'm definitely not asking you to do it! Looks like it's definitely a dupe of 2873! I'm already working on this because it's sort of a blocker on our ability to use Rollup since plugins like html-fill or html-entry just don't allow the level of control over the output-ted html.

I do have questions though!

Which hook would I need to use to setup tracking dependencies for an html file? I assume I'd call emitAsset on the parent html file (if it were the entry), and emitChunk on the imported files (via link or script). That's one of the several places I'm a bit stuck.

Can I set this up to have different behavior depending on what file is importing the html? (If it's an entry just create the html asset, if it's a javascript file import it as a string, for example).

None of the plugins I see use addWatchFile or anything like that...is that mostly automatic? Or do I need to explicitly add watches for each file I emit?

@lukastaegert
Copy link
Member

Ok, let me see if I can help you.

Which hook would I need to use to setup tracking dependencies for an html file? I assume I'd call emitAsset on the parent html file (if it were the entry), and emitChunk on the imported files (via link or script). That's one of the several places I'm a bit stuck.

First let me explain about emitAsset. This function is for emitting files that

  • you need to include in your output, but
  • you do not care about where they are placed or what they will be called in the end.

Because both of these things are to be configured by the user via a naming pattern. If this works for you, this is probably the preferred method of adding files due to the improved user control.

A good example for this is emitting an image file. As long as you have a way to reference it in the places that matter, you probably do not care where the file ends up. As for referencing, you can use import.meta.ROLLUP_ASSET_URL_${assetId} to reference them from JS code, or this.getAssetFileName(assetId) in the generateBundle hook (when the names are actually finalized). Note that you can still emit further assets in the generateBundle hook.

Now if you need to add a file to the bundle where you need full control over file name and directory, there is not yet a proper API (but it is high in my priority list). However, if you can just manually add them to the bundle in generateBundle as assets, i.e. an object {isAsset: true, fileName, source}. Then Rollup will write them to disc (or whatever the user does with the bundle).

Now for HTML files, I think there are two very distinct cases here, using HTML as an entry point and importing an HTML file. Using it as an entry point is not possible directly, see #2873 and the suggestions in that issue. In short, you can fake this by using the options hook to filter out html entry points and then emit stuff in the buildStart hook.

For referenced JavaScript files, you would want to use emitChunk and for other files (CSS?) you probably want to use either emitAsset or the other way I described above. Same for the HTML files itself, as you probably want to assemble an updated version in the generateBundle hook.

As for the importing case, this needs to be handled by providing a load hook that returns some proper JavaScript when the file is imported. E.g. if you want to return it as text, you might

load(id) {
  if (id.endsWith('.html') {
    // bonus points for using the non-sync version and returning a Promise
    return `export default '${fs.readFileSync(id)}'`;
  }
}

If you also want to emit chunks and assets in that hook, that is up to you.

Can I set this up to have different behavior depending on what file is importing the html? (If it's an entry just create the html asset, if it's a javascript file import it as a string, for example)

Tricky. What if both an entry point and a non-entry point import the file, which logic should apply? This is why the load hook does not tell you about importers as there can be a lot. You could try tracking the resolveId hook which will tell you all importers of a file. Otherwise I would probably use the hack outlined above and allow having HTML directly as entry point.

None of the plugins I see use addWatchFile or anything like that...is that mostly automatic? Or do I need to explicitly add watches for each file I emit?

addWatchFile is not for files that you emit but for your sources. The idea is that you can watch arbitrary files and if such a file changes, a Rollup run will be triggered. If you watch from a transform hook, this hook will also be guaranteed to be evaluated again (the idea is that a watch file is an external dependency that your transformation relies on).

Files that are imported never need to be watched manually as this is done automatically. So in our example, the files you want to watch manually are

  • HTML entry points if you want to use the hack I described
  • non-JS assets emitted from an HTML file

Everything else, i.e. emitted chunks, should be watched automatically.

I hope this helped a little.

@shellscape
Copy link
Contributor

If this plugin does approach completion, I'd be happy to vote for it as an official-of-sorts plugin and add it to the org here on Github. Moving forward, let's close this as pending-a-plugin and track the wider issue of handling assets on #2872.

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

No branches or pull requests

3 participants