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

Feature request: local context for entrypoints #7583

Closed
tedbyron opened this issue Jan 20, 2022 · 9 comments
Closed

Feature request: local context for entrypoints #7583

tedbyron opened this issue Jan 20, 2022 · 9 comments

Comments

@tedbyron
Copy link

🙋 feature request

local or browser-local entrypoint context for environments that load scripts locally.

🤔 Expected Behavior

If entrypoint has a local context, the script elements in the HTML page output should have neither type="module" nor nomodule attributes.

😯 Current Behavior

The HTML page fails to load both the type="module" script and the nomodule script. This is because the browser supports JS modules but there is no server serving the JS files, resulting in a CORS error or invalid MIME error.

💁 Possible Solution

If entrypoint has "context": "local", don't use type="module" and nomodule, just use the "fallback" script with type="text/javascript" attribute on the HTML element.

🔦 Context

I have an application that runs on specific hardware using a chromium browser locally and functions similarly to electron - uses an HTML entrypoint and necessary assets are fetched locally.

JS modules are supported by the chromium version but I get the error Failed to load module script: The server responded with a non-JavaScript MIME type of "". Strict MIME type checking is enforced for module scripts per HTML spec. because there is no server serving the JS files, they are only being loaded from the filesystem.

I've tried using "context": "electron-renderer", but this gives the same HTML output as "context": "browser". The only workarounds I could find were manually changing the HTML output and inlining the entire JS bundle (~1MB) which are not optimal.

The only similar issue I could find was this discussion.

💻 Examples

Build using parcel using an HTML entrypoint that has a JS script element and try to open the resulting HTML in the browser.

@mischnic
Copy link
Member

Did I understand you correctly that you want to view/run the output from Parcel via a file:// url without a werbserver?

@tedbyron
Copy link
Author

Did I understand you correctly that you want to view/run the output from Parcel via a file:// url without a werbserver?

Yes

@tedbyron
Copy link
Author

@mischnic differential bundling gives a fallback bundle and that works if I just remove the nomodule on it

@NothingEverWorks
Copy link

NothingEverWorks commented Jul 18, 2022

This is duplicated by #7959. Commenting here because this is still open.

I would like support for bundling for the file:/// procotol, but I actually prefer the possible solution from the duplicate feature request; a CLI flag. The advantage of a CLI flag is that it allows a project to be bundled for different usecases (e.g. for file:/// protocol or for a web server) without changing any configuration.

I've created a workaround in the following repo. https://github.com/NothingEverWorks/parcel-local-html
The workaround fixes the script tags after bundling by using the nomodule index.js output from the differential bundling, that already works with the file:/// procotol and supports synchronous import!

@DKFN
Copy link

DKFN commented Aug 22, 2022

That would be great 👍

Thanks a lot @NothingEverWorks for the inspiration. I had to adapt a the script for my use case but I can finally have a full automatic pipeline for the game GUI without having to manually modify the file.

Do you mind it if I package your idea in a new repository that -should- cover most use cases for the game and maintain it ?

I had to google way to much to find this !

@Ivanca
Copy link

Ivanca commented Jan 12, 2023

Parcel removing type="module" from script tags also means that you cannot using top-level async calls, instead one has to wrap them manually.

image

Parcel sells itself as the works-out-of-the-box alternative to webpack and then does stuff like this where it completely subverts basic expectations such as leaving type="module" intact.

@devongovett
Copy link
Member

Top level await: #4028

Leaving type="module" wouldn't fix that anyway, since modules are wrapped in a function in order to be bundled, therefore the await wouldn't be top-level anymore.

@github-actions
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs.

@github-actions github-actions bot added the Stale Inactive issues label Jul 12, 2023
@schwjm
Copy link

schwjm commented Feb 24, 2024

This issue still persists, can it be reopened? I'm hitting the lack of apparent support for local-filesystem JavaScript due to magic that was being done before but isn't now.

At the least, the migration document could do more to explain how to change things for this use-case.

@parcel/transformer-js: Browser scripts cannot have imports or exports.

  D:\code\pso-tracker\src\index.js:1:1
  > 1 | import PaletteProfiles from './modules/PaletteProfiles';
.
.
.
  💡 Add the type="module" attribute to the <script> tag.

The hint is useless because I run into CORS problems with running a local file.

A workaround I found is to change to a more raw form of import.

var PaletteProfiles;
import('./modules/PaletteProfiles.js').then((x) => { PaletteProfiles = x.default; })

This worked for importing data. When dealing with a class, I did not have success in shipping the class outside of the then callback directly ("x is not a constructor"), but another workaround sufficed because I just needed to instantiate the class immediately and only once anyway.

Before

import SaveData from './modules/SaveData';
var saveContainer = new SaveData(localStorage);

After

var saveContainer;
import('./modules/SaveData.js').then((x) => { saveContainer = new x.default(localStorage); })

For classes that needed instantiation later and multiple instances, this was trickier, as I had to make another scaffholding constructor function and store a lambda function off that passed in parameters, so that the scaffholding could use the exported default class.

Considering this worked in Parcel 1 with "nice module syntax", it'd be good to have this option, as the local web app was my only target. My workaround still has other issues to figure out and I'm not optimistic that I'll have a clean solution when it's done.

@github-actions github-actions bot removed the Stale Inactive issues label Feb 24, 2024
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

7 participants