Consequences of absent main.css with 'yarn start' (Sage 9)



Hey guys,

So after reading the discussion here (Sage 9 main.css 404 on devUrl), I more or less understand the intent in not providing the built main.css under dist when running yarn start, and only generating that file on yarn build. However, because we have a not-so-flexible deployment system (WP Engine), this has some less than ideal implications for us in our development process.

WP Engine, as far as I can tell yet, doesn’t offer a way for us to execute post-receive commands on the server, like rebuilding the theme. Consequently we have to track our dist files in our git repo, because that’s the only way we can use git push to deploy our code to WP Engine’s staging & production servers. It works great for us, only just means we have a little extra crap in our git repo, which we’ve been able to tolerate fine.

During development, we generally just keep our watch/browsersync session running in the background constantly, and commit our code fairly routinely, including deploying to staging from time to time to demonstrate functionality to coworkers or clients. With our other themes we’ve built (most use gulp in combo with browsersync), we’re used to expecting the dist folder to be always up to date with the compiled CSS.

However, this is no longer the case with Sage 9. We have to run yarn build every time we deploy to staging. And ideally, every individual commit’s dist files would be in sync with that commit’s source files.

So I’d really prefer it if the main.css file in dist could be getting rebuilt in the background as browsersync is running; would just make things a lot less cumbersome for us.

As it works now, I’m looking into finding a way to automatically run yarn build before each local commit; not overly familiar with git hooks but I imagine it’s possible.

Another thing to point out is that you’re probably going to keep getting people complaining about this intended behaviour of 404s in the console. Red error notifications in the Chrome console aren’t typically something that is easily overlooked by seasoned developers… or maybe that’s just me. I find it hard to remind myself to ignore any console error and accept it as normal.

Anyway, besides this one little issue, I love Sage 9 (as if I didn’t love Sage 8 enough) and can’t really say enough good about your design of this product.



Well I’ve come up with a workaround that seems to do the trick to ensure built files are properly tracked, in case anyone else is facing this issue. I created a pre-commit hook in my local git directory .git/hooks, and it looks something like the following. (This is assuming OS X, with your git repo is based in your WordPress root.)


# Cause script to fail if any command fails.
set -e

# Ensure PATH is set right in case this is run from a git client that wasn't
# launched from the terminal.
export PATH=/usr/local/bin:$PATH

# Enter theme directory, request pre-commit build of theme to ensure dist is
# accurate, and return to repository root directory.
pushd $THEMEDIR > /dev/null
yarn build
popd > /dev/null

# Add newly built files to commit.
git add --all $THEMEDIR/dist


So, I know this thread (Sage 9 main.css 404 on devUrl) has been locked for whatever reason, but I have two new complaints to add to the list of inconveniences related to the absence of main.css while having yarn start running.

One of the contributors to that thread pointed out another shortcoming: Using the TinyMCE’s editor in the backend, if your session isn’t a BrowserSync session, doesn’t work great because the browser can’t find main.css to style it the way you’d expect it to be styled. In my case, it’s unable to show the CSS whether I access the backend via localhost:3000 or The only way I can see the TinyMCE styles is if I had just run yarn build without yarn start running.

That seems like a pretty serious dev workflow shortcoming, considering how sweet it is that Sage provides TinyMCE styling out of the box; you’d think it’s something you’d want the developer to be able to test easily while having yarn start running in the background.

And here’s another problem I’m coming up against: Right now I’m working on my theme’s UX as it relates to initial page load, which involves hidden content and transitions that reveal content. It’s not playing nicely with the way the CSS is getting injected via JS because of how the page first starts with no CSS, and initial styling of elements is affected as a result, which interferes with my JS revealing code. I’m trying to test this as closely from the point of view of a member of the public as possible, from the initial page load, so I’m deliberately bypassing BrowserSync to run these tests (accessing directly via But even on the loading of CSS is noticeably delayed and causing problems with the UX; I guess webpack is what injects the CSS?

I need that CSS to be available as an up-to-date, static file to test my theme properly.

The only alternative is for me to halt yarn start and each time I change the code, run yarn build, then reload the page. Even just not having to run yarn build every time would make my life a lot easier.

With Sage 8, I had none of these issues. But in Sage 9, this is really proving to be a nuisance.

Anyone else here feeling similarly? And is there something I can easily do in the build scripts to ensure main.css is preserved and kept up to date while yarn start is running?


This is only based on ~20 minutes of digging around and poking things, but I found the following things that might set you on the right path:

This check of webpack.config.js is what prevents your CSS files from being written out when yarn initially starts:

new ExtractTextPlugin({
      filename: `styles/${assetsFilenames}.css`,
      allChunks: true,
      disable: (config.enabled.watcher), // This part right here

By commenting out the disable property (or setting it to hard false), you can get yarn start to generate your CSS…but only when you initially run it (i.e. it doesn’t regenerate when files are changed). :frowning:

Further down the line in webpack.config.js is this conditional, which fires up the browsersynce/hot module reloading if you’re watching:

if (config.enabled.watcher) {
  webpackConfig.entry = require('./util/addHotMiddleware')(webpackConfig.entry);
  webpackConfig = merge(webpackConfig, require('./'));

It’s possible you could either remove that or edit to set up your own watch pipeline that re-fires ExtractTextPlugin and/or replaces HMR w/ a more traditional BrowserSync implementation. This thread seems like it might have some helpful stuff for setting up a workflow that regenerates a file and loads that, instead of just passing CSS directly to the browser (as Sage 9 currently does).


Thanks @alwaysblank! I’ll try giving this a shot…