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

Release 1.5 #8327

Merged
merged 263 commits into from May 30, 2017
Merged

Release 1.5 #8327

merged 263 commits into from May 30, 2017

Conversation

benjamn
Copy link
Contributor

@benjamn benjamn commented Feb 7, 2017

Just as Meteor 1.4.2 took aim at rebuild performance, Meteor 1.5 will be all about production app performance, specifically client-side application startup time.

The banner feature of this effort will be first-class support for dynamic import(...), which enables asynchronous module fetching (sometimes referred to as "code splitting"). Jump to this comment for an overview of how it works.

As usual, this release will include any bug fixes since Meteor 1.4.3, though special attention will be paid to pull requests and issues that affect the performance of running applications.

You can update to the latest release candidate final release by running:

meteor update --release 1.5

Even though localStorage is a synchronous API, I wrote this code in an
asynchronous style so that we can easily switch to an async API when/if
that becomes preferable.

While localStorage has stricter size limits than IndexedDB, retrieving
data from IndexedDB is unbelievably slow (~10ms for each cache.check
call). When developing locally, that delay pretty much destroys any
benefit from caching.
@benjamn benjamn added this to the Release 1.5 milestone Feb 7, 2017
@benjamn benjamn added the in-development We are already working on it label Feb 7, 2017
@laosb
Copy link
Contributor

laosb commented Feb 8, 2017

Good to see the first beta! Is code splitting available at this time?

We (@abernix and I) suspect the intermittent "died unexpectedly" failures
of `meteor --get-ready` on Circle CI are due to hitting their (low) limit
on the maximum number of open files.

Although optimistic caching speeds up rebuilds considerably, it doesn't do
much for initial builds, and it definitely keeps more files open.
Disabling it here seems worth a try.
@benjamn
Copy link
Contributor Author

benjamn commented Feb 8, 2017

@laosb It should be working (after you meteor add dynamic-import), but unfortunately there seem to be some problems with the published beta releases. Specifically, import(...) isn't getting compiled into module.dynamicImport(...). I'll have to take a closer look at that tomorrow!

@benjamn
Copy link
Contributor Author

benjamn commented Feb 8, 2017

Okay! The problem was that I hadn't republished the ecmascript package as part of the beta release. Only babel-compiler had really changed, but ecmascript has a dependency on babel-compiler, so it needed to be republished as well.

With that minor snag out of the way, I'm happy to announce that you can try import(...) yourself right now (on Mac and Linux; still waiting for Meteor 1.4.2.6 to finish publishing on Windows).

Just run the following commands:

meteor create --release 1.5-beta.2 dynamic-import-test
cd dynamic-import-test
meteor add dynamic-import
meteor npm install --save react

Now, in dynamic-import-test/client/main.js, you can import react asynchronously when the "Click me" button is pressed:

Template.hello.events({
  'click button'(event, instance) {
    // increment the counter when button is clicked                                                                                                                                                                                                                                                                                                                         
    instance.counter.set(instance.counter.get() + 1);
    import("react").then(React => {
      console.log(React);
    });
  },
});

You can inspect the websocket frames in the "Network" tab of the Chrome Dev Tools to see that the code is being fetched over the network the first time the button is pressed.

In addition to importing npm packages, try creating a file called client/imports/dynamic.js and then import("./imports/dynamic.js").then(d => ...) in client/main.js. It's important that it's in an imports directory so that it won't be eagerly imported until you import(...) it.

The same syntax works on the server, though of course it's more interesting on the client.

@klaussner
Copy link
Contributor

klaussner commented Feb 8, 2017

Dynamic imports are working great so far! 😍 Just two remarks:

  • If an npm package is imported by both an eagerly loaded and a dynamically imported module, import(...) throws Uncaught (in promise) Error: Cannot find module '<npm package>'. Reproduction here.

  • Given that mostly large applications will benefit from dynamic import, the small localStorage quotas granted by browsers (5 MB on Chrome, 2.5 MB on Safari) could be a problem. Even more so if localStorage is used for application data as well.

@benjamn
Copy link
Contributor Author

benjamn commented Feb 8, 2017

@klaussner I tried using IndexedDB (via https://npmjs.org/package/localforage), but access times were unbelievably slow (5-10 milliseconds per query).

Any thoughts about alternative client storage mechanisms? It's possible we could just rely on HTTP caching, though that would mean not using a web socket.

I suppose we could use IndexedDB if we loaded the manifest (module identifiers, hashes) into memory eagerly when the application started (probably in this file). That way we wouldn't have to pay the API tax every time we check the cache.

I think `real` is a better antonym for `meta`, and I appreciate that
`real` and `meta` are both four letters long.
Also, the regular expression for removing existing source map comments now
matches only if the comment starts at the beginning of a line, following
previous behavior more closely.

To get this exactly right, we would need to tokenize the source to avoid
matching comments in string literals, for example, but that's hard because
this logic needs to work for multiple file types, not just JavaScript.
@tcastelli
Copy link
Contributor

tcastelli commented Feb 9, 2017

With the proposed solution of in-memory management of identifiers and hashes, maybe something like this could be useful https://github.com/dumbmatter/fakeIndexedDB

Also searching around I found these, which have adapters to persists with indexedDB but use indexes for fast queries once sync is done.

@laosb
Copy link
Contributor

laosb commented Feb 9, 2017

Hooray! Good to see that!

Actually we should have a suggested application structure for dynamic imports

@karldanninger
Copy link

Weeeeeee!!!!! This is fantastic news! Thanks @benjamn <3

@benjamn
Copy link
Contributor Author

benjamn commented Feb 9, 2017

Question: should the localStorage/IndexedDB caching be enabled in development, or only in production? It seems to complicate the mental model in development, especially if you're developing multiple apps using the same storage domain (http://localhost:3000), and it doesn't really save time because everything's loaded from localhost.

@benjamn benjamn merged commit bf85eac into master May 30, 2017
@abernix
Copy link
Contributor

abernix commented May 30, 2017

👏 🎉 🥇.⓹ 💥 Wooooohooooo! Hurrah! 💥 🥇.⓹ 🎉 👏

@d62remi
Copy link
Contributor

d62remi commented May 30, 2017

👍👍👍

@macrozone
Copy link
Contributor

<3

@benjamn
Copy link
Contributor Author

benjamn commented May 30, 2017

The Meteor 1.5 release is now final, though you'll still need to run meteor update --release 1.5 to get it, rather than just meteor update. After the announcement blog post goes up tomorrow, we'll officially "recommend" the release, which will make meteor update work.

If you already miss living on the bleeding edge, now that Meteor 1.5 is out, there's a new edge to play with over here: #8728

@jessb321
Copy link

Woot! 🎉

@mjmasn
Copy link
Contributor

mjmasn commented May 31, 2017

@abernix the new bundle-visualizer package is awesome!

@sferoze
Copy link

sferoze commented May 31, 2017

@mjmasn how do you use this package? There is no info in the repo https://atmospherejs.com/meteor/bundle-visualizer

@stubailo
Copy link
Contributor

You just add it I think! Then start your app.

@mjmasn
Copy link
Contributor

mjmasn commented May 31, 2017

@sferoze

meteor add bundle-visualizer then run meteor with --production

For two of our older apps I needed to meteor npm i -S meteor-node-stubs as well. Not sure if that's added automatically these days.

You also have to remove the bundle-visualizer package before deploying so I guess it's not totally ready for prime-time. Difficult one though because it has to run in production mode and can't tell if you're actually running locally with --production or actual production (although I'm sure there are ways to solve this).

@sferoze
Copy link

sferoze commented May 31, 2017

thanks @stubailo @mjmasn

I added it and it's awesome! Already helped me reduce the app size

@dr-dimitru
Copy link
Contributor

dr-dimitru commented May 31, 2017

Dynamic import() reduced our app size from ~4MB to ~800KB, awesome, thanks a lot MDG!
So solve this task quickly we've added dynamic import() support directly to flow-router - more info here

@ducdev
Copy link

ducdev commented May 31, 2017

Incredible !

@michaelb-01
Copy link

This looks great, is there an example project using angular (2 or 4) with Meteor 1.5 anywhere?

@abernix
Copy link
Contributor

abernix commented May 31, 2017

I've created (via 791d0cd) a README for bundle-visualizer on Atmosphere which provides information about how to use the bundle visualizer in conjunction with Meteor 1.5. Take a look at it and see if it provides more information and feel free to open a pull-request if you find any inaccurate information or something additional which might be helpful. The file can be found here in this repo.

/cc @sferoze

(And thanks to @mjmasn for providing the details above).

@vladejs
Copy link

vladejs commented May 31, 2017

Issue when upgrading from 1.5-beta.14 to 1.5 with a Buffer object.
deepinscreenshot20170531093748

Note: I use the uploader package ostrio:files. By using this package I had to npm i file-type fs-extra too. But in any case the above issue arises.

@dr-dimitru
Copy link
Contributor

Hi @vladejs ,

Weird we don't use Buffer on the client see veliovgroup/Meteor-Files#434 and #8645 (comment)

// this is an expensive polyfill for clientside Buffer usage
// but we recommend you refactor to remove this dependency
global.Buffer = global.Buffer || require("buffer").Buffer; // eslint-disable-line

// how to refactor
// you can easily drop a breakpoint on the error in your browser's inspector, then refresh the page to hit the breakpoint and see via the call stack which package is trying to use Buffer
// https://github.com/meteor/meteor/issues/8645

Hope this will fix it, I'm on major update of ostrio:files translating to ES6 (now it's CoffeeScript), so it should be fixed soon.

@p3pp8
Copy link

p3pp8 commented May 31, 2017

** SOLVED **
Angular UIRouter 1.0.3 stopped working again after updating the project to release 1.5 and after these upgrades:

babel-compiler             upgraded from 6.18.2 to 6.19.1
boilerplate-generator      upgraded from 1.0.11 to 1.1.0
dynamic-import             added, version 0.1.0
ecmascript                 upgraded from 0.7.3 to 0.8.0
ecmascript-runtime         upgraded from 0.3.15 to 0.4.1
ecmascript-runtime-client  added, version 0.4.1
ecmascript-runtime-server  added, version 0.4.1
meteor-base                upgraded from 1.0.4 to 1.1.0
minifier-js                upgraded from 2.0.0 to 2.1.0
minimongo                  upgraded from 1.0.23 to 1.2.0
modules                    upgraded from 0.8.2 to 0.9.0
modules-runtime            upgraded from 0.7.10 to 0.8.0
mongo                      upgraded from 1.1.17 to 1.1.18
promise                    upgraded from 0.8.8 to 0.8.9
reactive-dict              upgraded from 1.1.8 to 1.1.9
standard-minifier-js       upgraded from 2.0.0 to 2.1.0
webapp                     upgraded from 1.3.15 to 1.3.16

SORRY, it was because of static templates, not depending of uiRouter or Meteor 1.5!!!
GREATE RELEASE!!!

@CaptainN
Copy link
Collaborator

After upgrading to meteor 1.5 (from 1.5-rc.7), my app had been running with meteor-tool/1.4.x.x (as revealed by the path in my terminal title bar) - is that a problem? It would run meteor-tool/1.5.0.xxxx when doing an update.

I start meteor with meteor npm start which invokes the script "start": "meteor --settings settings-development.json" from package.json

I fixed it by uninstalling and reinstalling meteor from scratch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in-development We are already working on it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet