Skip to content

Conversation

@rkostrzewski
Copy link
Collaborator

Closes #101.

Tested in Chrome on desktop & mobile and IE 11. Chrome doesn't complain about document.write (ofc I've used typeof fetch === "function"). Rendering is not blocked in IE. 😄

@rkostrzewski rkostrzewski requested review from developit and lukeed June 20, 2017 23:31
minify: true,
stripPrefix: config.cwd,
staticFileGlobsIgnorePatterns: [
/polyfills\.js$/,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you ignore this because all serviceWorker-compatible browsers don't need a fetch or Promise polyfill?

(^ I'm not certain that that's 100% true)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I understand serviceWorker implementation requires fetch implementation which in turn requires Promise implementation. Based on FetchEvent. I could be wrong tough.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, right. I believe that's the case too 👍 You upgraded my 90% certainty to 95% 😉

<%= htmlWebpackPlugin.options.ssr({
url: '/'
}) %>
<script>"undefined"==typeof fetch&&document.write('<script src="<%= htmlWebpackPlugin.files.publicPath + "polyfills.js" %>"><\/script>')</script>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about (window.fetch===void 0) && ...?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds great! I'll change it to window.fetch==void 0&&document.write(...) (5 less characters & html webpack plugin doesn't minify inline script 😢 )

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lol okay. I was just going for perf since !== void 0 is faster than typeof === 'undefined'

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we're changing, maybe just go with window.fetch || document.write(..).

Copy link
Member

@developit developit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awesome - I was trying to do the exact same thing locally before I ended up going with the alias+ensure() setup but I couldn't get it working. It pains me ever so slightly to have a blocking document.write of a script in our HTML though - any thoughts on working around that?

<%= htmlWebpackPlugin.options.ssr({
url: '/'
}) %>
<script>"undefined"==typeof fetch&&document.write('<script src="<%= htmlWebpackPlugin.files.publicPath + "polyfills.js" %>"><\/script>')</script>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we're changing, maybe just go with window.fetch || document.write(..).

@developit
Copy link
Member

Randomly commented in my review - do you guys think we could do something like this to work around using a blocking document.write(<script>)?

<body>
  <script src="/bundle.js" defer></script>
  <script>window.fetch || document.body.appendChild(document.createElement('script')).src='/polyfills.js';</script>
</body>

@ethanroday
Copy link
Contributor

@developit Why not split out Promise from the rest of the polyfills and then take the approach you mentioned?

<script>window.Promise || document.body.appendChild(....</script>

Then the rest of the polyfills could just be loaded as normal from webpack.

@thangngoc89
Copy link
Collaborator

@ethanroday currently, preact-cli only includes Promise and fetch. And you need promise supports for fetch anyway. So no splitting needed

@lukeed
Copy link
Member

lukeed commented Jun 21, 2017

Doesn't it have to be blocking in order to ensure it loads before bundle?

@developit
Copy link
Member

@lukeed I wasn't sure if the async script (via createElement) would defer the defer script since those wait for document completion.

@rkostrzewski
Copy link
Collaborator Author

@developit so I've done my research.

document.body.appendChild(document.createElement('script')) doesn't block deferred scripts (kinda makes sense because defer only works for initial html, which document.write kinda mutates) so document.write has to stay. Good thing is document.write(<script>) does not block render (tested in Chrome & IE 11).

I've changed async to defer to preload bundle.js and added parsing blocking document.write. Tested in all IE >=9, latest Edge, Chrome, Firefox and android 4 browser. All is well 😄

@lukeed
Copy link
Member

lukeed commented Jun 22, 2017

@rkostrzewski Makes sense, that's what I had "remembered" too.

However, I'm worried that changing from async to defer will hurt our load time. It shouldn't matter which attribute the main bundle is using since document.write is first & blocks, right?

@rkostrzewski
Copy link
Collaborator Author

@lukeed perf should be pretty much the same for async & defer when using only one script. Additionally, <script> tag doesn't block <script async> as they are executed as soon as they are downloaded and stack is empty. bundle.js is much smaller than polyfills.js for initial project which means that it will most likely be downloaded earlier and executed earlier <- Promise doesn't exist yet - require.ensure & import() fail.

tl;dr async is random 😛

@lukeed
Copy link
Member

lukeed commented Jun 22, 2017

Haha okay 😆 Thanks!

<% for (var chunk of webpack.chunks) { %>
<% if (chunk.names.length === 1 && chunk.names[0] === 'polyfills') continue; %>
<% for (var file of chunk.files) { %>
<% if (htmlWebpackPlugin.options.preload && file.match(/\.(js|css)$/)) { %>
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW htmlWebpackPlugin.options.preload comes from argv.preload which is a hidden switch that can't be used. Gonna check whole codebase for hidden switches sometime soon.

Copy link
Member

@lukeed lukeed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't check out locally but looks good to me!

@rkostrzewski
Copy link
Collaborator Author

rkostrzewski commented Jun 25, 2017

@lukeed gonna fix regex coz I just noticed it is wrong ([bundle|polyfills] should have been (bundle|polyfills). Also package-lock.json should not been comitted I guess.

@reznord
Copy link
Member

reznord commented Jun 25, 2017

@rkostrzewski you are using npm5.x? I thought it wasn't that stable and it has many issues.

@rkostrzewski rkostrzewski added this to the 1.2.0 milestone Jun 25, 2017
@rkostrzewski
Copy link
Collaborator Author

@reznord works good enough for me. Hadn't had any issues yet.

@reznord
Copy link
Member

reznord commented Jun 25, 2017

I was had issues with it when I was working with react-native, so thought of upgrading later.

@reznord
Copy link
Member

reznord commented Jun 25, 2017

any issues which I can take over?

@rkostrzewski rkostrzewski merged commit 5a56336 into master Jun 25, 2017
@rkostrzewski rkostrzewski deleted the fix/promise-polyfill branch June 25, 2017 07:34
@rkostrzewski
Copy link
Collaborator Author

@reznord if you want feel free take anything with help wanted label 😄

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

Successfully merging this pull request may close these issues.

7 participants