ember-auto-import
ember-auto-import copied to clipboard
Breaks when using script defer
I have an app that is not using ember-auto-import in its application code (as far as I can tell).
I noticed that I get a runtime error:
l.js:2 Uncaught ReferenceError: require is not defined
at eval (l.js:2)
at Object.../../../../../tmp/broccoli-20413LssqYisKTYOQ/cache-305-webpack_bundler_ember_auto_import_webpack/l.js (chunk.app.9a9a5f13351ef9d0df2b.js:29)
at __webpack_require__ (chunk.app.9a9a5f13351ef9d0df2b.js:53)
Where l.js is:
window._eai_r = require;
window._eai_d = define;
When I remove ember-auto-import from my devDependencies, the error goes away.
I would just remove it, but according to https://github.com/emberjs/ember-qunit/blob/master/docs/migration.md it is needed for ember-qunit for the tests (although the tests do work without it, as far as I can tell :thinking: )
What version of ember-auto-import?
What were you changing when this problem appeared?
Not 100% sure, as the app did not fail (and tests passed), the error is only visible in the console (which I only just noticed).
I would guess it happend when upgrading from ember-auto-import 1.x to 2.x - I just tried downgrading it and the error went away!
I will try to see if I can get a reproduction somehow...!
OK, after a lot of trial and error, I found the culprit!
In this app, defer was added to the vendor JS file in index.html:
<script src="{{rootURL}}assets/vendor.js" defer></script>
As it uses fastboot/prember and thus does not need the JS to work.
It works if:
- I remove
defer - or I downgrade to ember-auto-import v1
- If I visit
/testsit also does not trigger the error
Here is a reproduction repo: https://github.com/mydea/ember-issue-reproductions/commit/4948624aa766b1d12edc067b545e0d096a630d13
We need to find a clearer place to document this, but this is a known limitation, see https://github.com/ef4/ember-auto-import#customizing-build-behavior:
publicAssetURL: the public URL to your /assets directory on the web. Many apps won't need to set this because we try to detect it automatically, but you will need to set this explicitly if you're deploying your assets to a different origin than your app (for example, on a CDN) or if you are using
I've encountered the same issue when upgrading to v2. Application uses defer for scripts, and the config already contains publicAssetURL: '/assets', I've also tried publicAssetURL: 'http://localhost:4200/assets', but with no luck.
Should the combination of defer and publicAssetURL: '/assets' work out of the box?
This is a duplicate of #418.
Even when using the new insertScriptsAt I'm unable to use defer in scripts after 2.x I tried with and without publicAssetURL. Not sure if I'm not understanding the new syntax, but this seems like a regression from 1.x.
Isn't the issue here that defer causes the script to be loaded and evaluated asynchronously, and the eai generated chunk probably runs before vendor.js, which would explain why require and define are undefined?
Deferred scripts are guaranteed to run in order...
Scripts with the defer attribute will execute in the order in which they appear in the document. MDN
But I haven't found a definite answer to the question what happens when a normal script follows a deferred one. I think it wouldn't make much sense if the normal script would wait for the deferred one, as then there is no deferring happening at all.
But that would mean that the eai generated chunk that contains window._eai_r = require; runs after vendor.js in this scenario:
<script src="/assets/vendor.js" defer></script>
<script src="/assets/app.js" defer></script>
<script src="/assets/chunk.12345.js"></script>
Maybe we must make eai also add defer to the scrips tags in generated in this case?
We've managed to get this working as documented now with app/index.html containing.
<script defer src="{{rootURL}}assets/vendor.js"></script>
<auto-import-scripts defer entrypoint="app"> </auto-import-scripts>
<script defer src="{{rootURL}}assets/app.js"></script>
and our ember-cli-build.js with:
autoImport: {
insertScriptsAt: 'auto-import-scripts',
},
@jrjohnson Thanks for sharing, cool that this works now!
I think it's a bit unfortunate that this is kind of "insider info". I expect this to have quite a positive effect, have you measured this change in term of e.g. Lighthouse score?
Maybe this should be the default when installing FastBoot, e.g. by modifying index.html with ember-cli-fastboot's default blueprint?
@ef4 what about Embroider? This PR seems related, but doesn't cover all what eai has here. Should we aim for feature parity, by introducing the same in Embroider?
Yes, we should land the feature in https://github.com/embroider-build/embroider/pull/588 for embroider as well.