Skip to content
This repository has been archived by the owner on Apr 25, 2019. It is now read-only.

Framework: Extract styles into 2 separate css files for better distribution and debugging #627

Merged
merged 13 commits into from
Sep 28, 2016

Conversation

Tug
Copy link
Contributor

@Tug Tug commented Sep 7, 2016

This PR extracts the generated CSS into 2 separate external styleshets for ltr and rtl languages.
This has a few advantages over the current solution:

  • It divides the build size and build time by 2
  • It simplifies the build script
  • We manage JS and CSS separately as it is supposed to be
  • User who switches from an ltr to an rtl (or vice-versa) language won't have to download the whole bundle again, just the stylesheet.

Testing Instructions

  • git checkout update/external-css
  • npm i
  • npm run start:static
  • Check public/scripts and assert that only 1 script (and it's mapping) is present and is minified
  • Check public/styles and assert that 2 stylesheets are present (along with reset.css) and that those stylesheets are minified
  • Navigate to http://delphin.localhost:1337/ and try switching languages, you shouldn't have any css issues

Reviews

  • Code
  • Product

@Tug Tug added the blocked label Sep 7, 2016
@Tug Tug force-pushed the update/external-css branch 2 times, most recently from 5d1fec0 to 07140b7 Compare September 12, 2016 08:58
@yurynix
Copy link
Contributor

yurynix commented Sep 12, 2016

Here's what I think we should do as a short-term solution:

A better solution might be split webpack-rtl-plugin to 2 parts: loader and a plugin, the loader collects all the css and RTLifies them, later the plugin will emit an additional css.

@Tug
Copy link
Contributor Author

Tug commented Sep 12, 2016

About romainberger/webpack-rtl-plugin#5

This is a general plugin and I don't believe we should minify by defaut assets other than the one this plugin is responsible for.
If we do we should at least make it optional using a parameter.

On 12 Sep 2016, at 13:25, Yury Michurin [email protected] wrote:

Here's what I think we should do as a short-term solution:

Lets upgrade to webpack2 #650
Make all the css non minimized ( that will happen after #650 on itself, since we don't actually minify them anywhere ( we don't have css?minimized) )
Use romainberger/webpack-rtl-plugin#5 to minify both the RTL css and the original css
A better solution might be split webpack-rtl-plugin to 2 parts: loader and a plugin, the loader collects all the css and RTLifies them, later the plugin will emit an additional css.


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or mute the thread.

@yurynix
Copy link
Contributor

yurynix commented Sep 12, 2016

@Tug I think it should, it already does it for the RTL css.

@yurynix
Copy link
Contributor

yurynix commented Sep 13, 2016

I've pushed a commit that makes everything work™

It does that by referencing directly to:

"webpack-rtl-plugin": "yurynix/webpack-rtl-plugin.git#test-build",

romainberger/webpack-rtl-plugin#5

and:

    "psuedomap": "bmb330/pseudomap",

isaacs/pseudomap#6

When you run:

npm run start:static

You'll get the correct RTL version:
screen shot 2016-09-13 at 11 56 22 am

And the build artifacts will be be:
screen shot 2016-09-13 at 11 57 07 am

@Tug
Copy link
Contributor Author

Tug commented Sep 13, 2016

Indeed it works! Congrats @yurynix
I'm moving this to blocked while we upgrade to webpack2 and use nice package dependencies for all those.

@Tug Tug force-pushed the update/external-css branch 3 times, most recently from 958b54c to 08142a0 Compare September 26, 2016 16:30
@Tug
Copy link
Contributor Author

Tug commented Sep 26, 2016

I had to build and publish the forked version of webpack-rtl-plugin here. I guess it's because npm prepublish is not called anymore on install so it's installed in delphin without lib/index.js which caused a failure.
I also tried to publish the package as @automattic/webpack-rtl-plugin on npmjs.org but those are for private packages only and I believe only registered&allowed npm users can actually install those.

Anyway it works now I think we're ready for a review!

Copy link
Contributor

@drewblaisdell drewblaisdell left a comment

Choose a reason for hiding this comment

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

This looks great. I left some notes, but they were mostly questions or references that I noticed that we should now remove. I agree that this is a good solution, and am mainly trying to understand the parts that confused me or the limitations of this and the previous solution.

We manage JS and CSS separately as it is supposed to be

  • Do we? We still use CSS modules, the withStyles HOC, and determine style names programmatically with JavaScript.
  • For my own understanding: why is this "as it is supposed to be"? It seems arbitrary, but provides an advantage in terms of code-splitting. Managing markup and JS separately is also "as it is supposed to be".

If we didn't support RTL, I don't think it would necessarily be an advantage, as we now have a global CSS file containing styles for every section of the site.

loaders: [
{
test: /\.jsx?$/,
loaders: [ 'react-hot' ]
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm betting this is my lack of knowledge about webpack showing, but why use react-hot in production instead of development?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's probably another error error here, thanks for noticing, I'm going to have to fix that and test again the different envs...

// Switches loaders to debug mode. This is required to make CSS hot reloading works correctly (see
// http://bit.ly/1VTOHrK for more information).
config.debug = true;

// Use a more performant type of sourcemaps for our development env
// For a comparison see: https://webpack.github.io/docs/configuration.html#devtool
// Enables source maps
Copy link
Contributor

@drewblaisdell drewblaisdell Sep 26, 2016

Choose a reason for hiding this comment

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

Minor, but is there a reason this comment changed? This is slightly misleading, as source maps are enabled in production.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure why it has changed but yeah we should keep the previous one

@@ -62,19 +61,24 @@ function renderPage( props, localeData ) {
const assets = JSON.parse( fs.readFileSync( path.join( 'public', bundlePath, 'assets.json' ) ) );
// `main` is an array of JS files after a hot update has been applied
const bundleFileName = typeof assets.main === 'string' ? assets.main : assets.main[ 0 ];
let stylesFileName = '';
if ( Array.isArray( assets.main ) ) {
stylesFileName = assets.main.filter( asset => ( isRtl ? /rtl\.css$/ : /[^rlt].css$/ ).test( asset ) ).shift();
Copy link
Contributor

Choose a reason for hiding this comment

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

I haven't tested this, so apologies if this is just my poor regex understanding, but do we need to escape the . in the alternative condition? Also, rlt seems like a typo, but I think those characters in a pattern like [^this] can be in any order - is that correct?

if ( window.localeData ) {
i18n.setLocale( window.localeData );
} else if ( currentRouteSlug ) {
switchLocale( currentRouteSlug );
Copy link
Contributor

@drewblaisdell drewblaisdell Sep 26, 2016

Choose a reason for hiding this comment

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

For my own understanding: how would this condition ever be reached?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree it's a bit confusing and I'm also having a hard time figuring out why I added this. I think it was made to display a localized 404 page using the locale slug. Since we're generating 404 pages now I don't think this is needed anymore.

@@ -26,5 +26,5 @@ export function addCss( css, styles ) {
}

export function insertCss( styles ) {
return styles._insertCss();
return styles._insertCss && styles._insertCss();
Copy link
Contributor

Choose a reason for hiding this comment

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

For my own understanding: why do we need this presence check now? If _insertCss isn't present in production/development, it might be worth commenting.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We need that check because _insertCss is added to every css modules by the isomorphic-style-loader I believe. In production we don't use that loader and we don't need to manually append css blocks to the page since we have a bundle so we're just ignoring this function.

"clean:all": "rm -rf node_modules && npm run clean",
"clean:i18n-cache": "rm -f server/i18n-cache/data/*",
"clean:static": "rm -rf public/static",
"generate": "npm run build && npm run build:static",
"generate:rtl": "BUILD_RTL=true npm run build && npm run build:static:rtl",
Copy link
Contributor

Choose a reason for hiding this comment

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

We still reference BUILD_RTL in the client webpack config. We should probably remove those ternaries.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep sorry, I didn't cleanup after rebasing

@@ -39,7 +38,7 @@ var config = {
},

postcss() {
return process.env.BUILD_RTL ? [ autoprefixer, rtlcss ] : [ autoprefixer ];
Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably remove the other reference to BUILD_RTL below in this file as well.

"hooks": "node hooks/manage",
"lint": "eslint --max-warnings 0 app client server && sass-lint --config .sass-lint.yml --max-warnings 0 --verbose",
"preinstall": "npm run-script clean",
"prod:static": "NODE_ENV=production npm install && NODE_ENV=production npm run generate && NODE_ENV=production npm run generate:rtl",
"prod:static": "NODE_ENV=production npm install && NODE_ENV=production npm run generate",
"qs": "npm run build && node server/build/bundle",
"qs:rtl": "BUILD_RTL=true npm run build && node server/build/bundle.rtl",
Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably remove this script, as well as start:rtl.

@drewblaisdell
Copy link
Contributor

I added a commit to address my notes about lingering BUILD_RTL references. I also noticed that we're attempting to load a non-existent stylesheet in development and added a commit to prevent this.

@Tug
Copy link
Contributor Author

Tug commented Sep 27, 2016

We manage JS and CSS separately as it is supposed to be

Do we? We still use CSS modules, the withStyles HOC, and determine style names programmatically with JavaScript.
For my own understanding: why is this "as it is supposed to be"? It seems arbitrary, but provides an advantage in terms of code-splitting. Managing markup and JS separately is also "as it is supposed to be".
If we didn't support RTL, I don't think it would necessarily be an advantage, as we now have a global CSS file containing styles for every section of the site.

I mean on production. I like the css module approach for developement but I don't think having our css bundled as text in our js is a good approach in production. Browsers are optimized to render css even before the js starts executing and I think generally we should keep doing what browsers would expect.
I agree we had a working "hack" thanks to the isomorphic style loader but I found it made the apps more complex (to grasp) for very little benefits and also duplicated a lot of data (styles) the user would have to download in the process.

@scruffian
Copy link
Member

The code looks good. I noticed that the hash on the LTR bundle is different to the RTL bundle. Is there a reason for that?

@Tug
Copy link
Contributor Author

Tug commented Sep 27, 2016

@scruffian yes there are different for 2 reasons:

  • It's based on the output before minification (which is different for ltr and rtl)
  • They don't use the same hash function

@drewblaisdell
Copy link
Contributor

Everything except CSS hot reloading in development seems to be working properly. When editing CSS, the app reloads but no new CSS is written onto the page.

@fabianapsimoes
Copy link
Contributor

Product 👍

Everything except CSS hot reloading in development seems to be working properly.
But maybe we want to resolve this before merging? I'm switching the label, but feel free to switch it back if it makes sense.

@Tug
Copy link
Contributor Author

Tug commented Sep 28, 2016

@drewblaisdell @fabianapsimoes actually this is broken in master as well, probably due to our upgrade to webpack2. We will need to fix that in another PR. Merging.

@Tug Tug merged commit 6508811 into master Sep 28, 2016
@Tug Tug deleted the update/external-css branch September 28, 2016 16:16
@fabianapsimoes
Copy link
Contributor

@Tug have you opened another PR already? Otherwise, we should create an issue so it doesn't fall through the cracks.

@Tug
Copy link
Contributor Author

Tug commented Sep 29, 2016

Now I have #683

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants