parcel icon indicating copy to clipboard operation
parcel copied to clipboard

Feature request: local context for entrypoints

Open tedbyron opened this issue 2 years ago • 5 comments

🙋 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.

tedbyron avatar Jan 20 '22 18:01 tedbyron

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

mischnic avatar Jan 20 '22 18:01 mischnic

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

Yes

tedbyron avatar Jan 20 '22 18:01 tedbyron

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

tedbyron avatar Jan 20 '22 18:01 tedbyron

This is duplicated by https://github.com/parcel-bundler/parcel/issues/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!

NothingEverWorks avatar Jul 18 '22 23:07 NothingEverWorks

That would be great :+1:

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 !

DKFN avatar Aug 22 '22 00:08 DKFN

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.

Ivanca avatar Jan 12 '23 23:01 Ivanca

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.

devongovett avatar Jan 12 '23 23:01 devongovett

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[bot] avatar Jul 12 '23 00:07 github-actions[bot]

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.

schwjm avatar Feb 24 '24 17:02 schwjm