-
-
Notifications
You must be signed in to change notification settings - Fork 7.2k
Replace sprockets/browserify with Webpack #2617
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
Conversation
…ckground cache updates
@ykzts Unfortunately, jQuery is still a dependency because of jquery-ujs which makes some non-GET links work. There is rails-ujs which is jQuery-free but it didn't work with webpack. jQuery is also used in public.js. On the upside, webpack splits the code into vendor.js and application.js/public.js bundles, so dependencies are not loaded twice. |
@Gargron Uh... As far as I see, |
The web UI has one logout button which needs jquery-ujs |
Oh... I see. Certainly. I'm sorry. |
I don't understand why view specs are failing with this cryptic error. I changed nothing about them... |
0fbd693
to
13a644f
Compare
config/webpack/production.js
Outdated
const webpack = require('webpack') | ||
const merge = require('webpack-merge') | ||
const CompressionPlugin = require('compression-webpack-plugin') | ||
const BabiliPlugin = require('babili-webpack-plugin') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure it's worthwhile to use both Babili and Uglify; AFAIK Uglify still produces smaller code than Babili, although the downside is that it only works on ES5, so e.g. if we wanted a pure ES6 build then that's the point where Babili would be very useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This article claimed that babili was preferable to uglify because it could understand the new syntaxes better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah so that doesn't really apply to tree-shaking; tree-shaking is about bundling ES modules, which is handled by Webpack 2 before the rest of the ES6-to-ES5 transpilation. You can test it, but I'm fairly certain Uglify alone (with mangle+compress) will still beat Babili, assuming you're outputting ES5 code. (In fact it looks like Babili's own benchmarks still show Uglify winning, although I know they're making progress.)
cascade: true, | ||
keep_fargs: false, | ||
warnings: true | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just setting compress
to true
should be fine, unless there' is something in particular you wanted to tweak here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was implementing suggestions from this comment: #1712 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dunno, most every JS project I know of just uses uglify with mangle
and compress
set to true
. You can tweak the compress settings in rare cases, but in my mind "mangle/compress" (aka uglifyjs -mc
) is basically Uglify's "default" setting. :)
warnings: true | ||
}, | ||
|
||
mangle: false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't often see mangle
set to false
, would this break something to turn on?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Afaik it would make trying to debug production errors way harder..?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A good solution for that is sourcemaps. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if mastodon published sourcmaps in prod I would be all about that. I personally like having mangle off otherwise though.
algorithm: 'gzip', | ||
test: /\.(js|css|svg|eot|ttf|woff|woff2)$/ | ||
}) | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be a good idea to also use the DefinePlugin
to ensure that NODE_ENV
is set to production
which cuts out a lot of development-only code in React as well as other libraries (React docs on the subject). I also opened up a PR for doing the equivalent thing in Browserify FWIW: #2635
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rails/webpacker sets NODE_ENV=production in bin/webpack
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh that's odd, React's docs still say to add DefinePlugin, but maybe it's no longer necessary for Webpack 2? Just checked the output bundles after asset:precompile
and I'm not seeing any NODE_ENV
references, so LGTM 👍
FWIW, just tested the bundle size, and before this PR |
Travis keeps breaking because node-sass needs some binaries that apparently don't get cached by Travis? |
Here are upgrade notes:
|
I'm not sure if you are happy for people to provide feedback here. This branch is live on glitch.social (thanks Bea). (Edit: typo) |
Gemfile
Outdated
@@ -58,18 +55,18 @@ gem 'sprockets-rails', require: 'sprockets/railtie' | |||
gem 'statsd-instrument' | |||
gem 'twitter-text' | |||
gem 'tzinfo-data' | |||
gem 'webpacker', github: 'rails/webpacker' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using the github:
style here produces a security warning on bundle install -- using https://....
will fix it.
But also, I think this is on rubygems now: https://rubygems.org/gems/webpacker/versions/1.2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. Just did what the webpacker readme recommended. Will gladly pin the version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah ... I think this was only possible once Rails 5.1 came out, and before that you DID need to pull from GH repo
@@ -1,6 +1,6 @@ | |||
body { | |||
font-family: 'Roboto', sans-serif; | |||
background: $color1 image-url('background-photo.jpg'); | |||
background: $color1 url('../images/background-photo.jpg'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems weird that the stylesheets move into app/javascript/...
-- is that normal for webpack?
@@ -0,0 +1,11 @@ | |||
@font-face { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question here ... it seems weird that the fonts move into app/javascript/...
-- is that normal?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not normal but if I leave anything in assets it will get picked up by sprockets, I think, and then it would get processed twice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I would have assumed that the JS moves to app/javascript but anything which really is still just a static asset either a) stays in app/assets (and is made available to the JS, where needed? I think webpack does this...?), or b) moves to like - app/fonts
or something?
The thing I'm asking about here isn't the move away from sprockets and to webpack, but about the naming convention of having fonts and images in an app/javascript
dir...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It isn't too weird really, as some React practices involve bundling CSS modules directly with components, e.g. CSS and JS side by side, with any relevant images included. We don't use that but it's still all close together.
@@ -8,6 +8,6 @@ | |||
|
|||
# Precompile additional assets. | |||
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added. | |||
Rails.application.config.assets.precompile += %w(application_public.js custom.css) | |||
# Rails.application.config.assets.precompile += %w(application_public.js custom.css) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this left commented out on purpose, or should be a delete?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's commented out by default so I left it commented out instead of deleting
Should we add a |
…ormance by using ImmutablePureComponent instead of React.PureComponent. ImmutablePureComponent uses Immutable.is() to compare props. Replace dynamic callback bindings in <UI />
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm approving this on the assumption that we continue to find edge cases and work out best practices once the bulk of it is in.
On second analysis, it looks like this didn't shrink the bundle size much. 😕
Looks like we're still at around 2.8MB of JavaScript total. I've run webpack-bundle-analyzer on the latest master branch (4d22d03); here's a live view of the data. A few things jump out at me:
Mostly I don't see any easy wins here; just need to assiduously go through dependencies and try to remove what's not needed, replace where possible, etc. Code-splitting would also be good. Keep in mind that Sean Larkin from the Webpack team recommends <300KB (without gzip) for each chunk, whereas Addy Osmani on the Chrome team recommends <100KB to hit <3 seconds on 3G. |
Since Webpack used from mastodon/mastodon#2617, it is necessary to start `webpack-dev-server`.
Dockerfile
Outdated
@@ -32,14 +30,14 @@ RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/reposit | |||
imagemagick@edge \ | |||
ca-certificates \ | |||
&& npm install -g npm@3 && npm install -g yarn \ | |||
&& bundle install --deployment --without test development \ | |||
&& yarn --ignore-optional --pure-lockfile \ | |||
&& yarn cache clean \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why remove yarn cache clean
task? for rails/webpacker#405 ?
Fix #1712, #1742
What this toolchain upgrade provides:
Untested potential benefits:
TODO:
Development implications:
./bin/webpack-dev-server
at the same time asrails s
yarn run manage:translations
to get a list of all missing/redundant translations in the web UI