Sage 9 + webpack

I wanted to learn to work with webpack and decided to create a version of Sage 9 that implements it. If interested, have a look at my fork (the branch is webpack-sage-9).

https://github.com/ptrckvzn/sage/tree/webpack-sage-9

I started from Austin Pray’s webpack branch and the example provided in the bootstrap-loader repo : bootstrap-loader/examples/basic at master · TongChia/bootstrap-loader · GitHub

It was hard to keep BrowserSync “hot” update css because the extract-text-webpack-plugin seems to prevent that. That’s the reason I went for a “dev” and a “prod” webpack config.

Some info :

  • generates an assets.json in the same format as the manifest expected by Sage minus the folder structure in dist/.
  • removed gulp & bower
  • load boostrap-v4.0.0-alpha2 via bootstrap-loader

The “dev” webpack config with browserSync server (dev.js):

  • bundle css in .js to allow “hot” loading
  • watch for changes in .php in templates/**/*
  • updates js changes with monkey-hot-loader

The “prod” webpack config :

  • extract css to a separate file
  • minify css with cssnano

There is some stuff to work out like a linter, imagemin, sourcemaps, add customizer.js and not load main.css in src/setup.php in dev mode as it is inlined in the main.js.

The install command : npm install && composer install

To start the dev watch mode (browsersync) : npm run dev

To build assets for production : npm run production

Any feedback welcomed and would definitely like to help out integrating webpack to Sage 9 !

17 Likes

This is great! I’ll definitely test it next week.

Let me know what you think!

I made some changes…

  • added eslint
  • added source maps
  • load customizer.js
  • removed bootstrap-loader : it’s simpler to load bootstrap in the main.scss and main.js
  • uses only one webpack config file and use a environment variables to change between production / development

The npm commands :
npm run build : build assets
npm run watch : watch mode
npm run production : build minimized assets

There are a few config variables / paths in webpack.config.js that needs to be changed per installation.

For the Browser Sync to work, the dev url must be specified in ./dev.js

Thanks for this!

The holdup on my end was that I was trying to keep the functionality the same as sage 8 (keep parity between Dev and prod). However: JS community has pretty much settled that they don’t care about that. For instance: react has debugging code that is stripped away when NODE_ENV=production. The vanilla webpack CLI also has a Dev and a production flag where dev doesn’t uglify. As such: I’m fine with making that change.

Probably shouldn’t drop gulp. It’s definitely not needed (I haven’t used in a while) but could be useful for non-JS type tasks like moving all the images in the image folder and adding them to the hash manifest. This isn’t a SPA so it’ll be challenging to run 100% of the asset pipeline through webpack.

Overall though: needs a bit of refactoring but we can run with this. I would ask that people clone this down and test to see if anything is missing compared to old sage.

@austin but even that image task (and many others) could be done by some webpack plugins or npm tasks.
Of course people could drop gulp and its dependencies after cloning the project (I’m sure I would) but honestly I don’t see the advantage anymore.

Very awesome Patrick! I was planning on working on something similar - glad I found this. I’ll clone it and check it out this weekend.

Thanks for the comments!

I’m using it on a project now. It’s a good exercise to see what needs fine-tuning. I added notifications to browser-sync so that I get visually notified when the bundle is being rebuilt.

The images & fonts specified in CSS url() are copied to the dist folder and renamed with an hash. I think there is a webpack loader to optimize the images that I will try to add.

I’m very open to refactoring. Actually that’s what I was hoping for by posting it that early. I’ve thrown all this together to figure out how things work. I know Javascript should be more uniform. Also, should a .json file replace bower’s manifest.json for the paths and dev server? I’m very open to all comments and have some time to make it better.

I’m also wondering if the npm commands shouldn’t be something different like :
npm run build
npm run build:production
npm run watch
but I was going to wait and see if there is not other commands to add like npm run lint for example. it could use the webpack -d and -p too. That could remove a few lines in the webpack config.

6 Likes

:blue_heart: thank you so much for working on this

I just rebased the sage-9 branch from master. Would you mind submitting a PR to sage-9 with the changes that you’ve made so far?

Would want to avoid anything custom such as https://github.com/ptrckvzn/sage/blob/d3982e7edb6adcd0ffd61cb86573933b4fee01d2/assets/styles/common/_variables.scss#L8-L12

With this setup will you still be able to make overrides? I often find that the styles indicated for the package are compiled instead of the source .scss files that allow you to preset configuration values.

Is there anything like Wiredep that could be implemented? I know this modular idea is very much used in Javascript frameworks, but for some presentational sites you really just need to pull in a few jQuery components to get things done.

Super!

Should I simply do this PR : https://github.com/roots/sage/compare/sage-9...ptrckvzn:webpack-sage-9 ?

Not sure why there is 82 files changed… I can’t hide that it will be my first PR. :stuck_out_tongue: Can’t wait to break out the champagne!

2 Likes

Might be better to do a fresh branch off our sage-9 branch and re-apply your changes, unless you want to go through the fun process of rebasing everything

1 Like

By the way, @patrickv & @ben, congrats on the merge & rebasing. I’ve been holding out on learning Sage and it’s workflow pending this kind of milestone within sage-9.

Notwithstanding tweaks & docs, it looks like it Bootstrap 4 may be the big holdup. No?

1 Like

All change again :slightly_smiling: For the better I’m sure.

I’m trying to get my head around this change. I’ve been ‘playing’ with it, but I can’t seem to get the main.scss to compile to the dist like the main.js and the customizer do (which I can see in webpack.config.js) is this missing from the file? If it is how do I add it?

OK , so Yes I’ve been dumb (well not dumb maybe, but ignorant to the way this new way all works), but I think I will leave this here, as it might help others on the toute to learn this new stuff like me.

Npm run build ( & then the npm watch ) is all you need, the css files are not sent to the dist directory, but are being loaded in via the .js files there.

I was thrown by the call in the head to a ’ … /dist//main.css’ file which didn’t exist. (side note, why the two // ?).

Yes, the css is inlined with the javascript. I updated my branch so that styles are extracted to a .css when running npm run build and inlined only when running the watch server so that it can be “hot updated”.

Sorry about the double-slash, i also fixed that - might be merged when people have the time to take another look. Work in progress! :slightly_smiling:

1 Like

Thanks :slight_smile: I’m slowly getting there. I’ve spent today getting to grips with it more.

Just need to figure out how I call in other scripts like I did with manifest.json in the past and I think I may have it.

It’s a bit tricky depending on the js package you’re importing. Some are imported in the header of you javascript file (assets/scripts/main.js) and some other needs to be added to the externals and/or webpack.ProvidePlugin() in webpack.config.js. I am taking some notes as I am working with it.

I think this is where I’m struggling with it (thanks for the tips above), before there was one place to do this, now I feel it’s a bit disjointed, and the sort of thing that if I came back to later I wouldn’t remember where to look (without the notes).

Hi Guys,

I could do with some direction. If I have a .scss file which controls styles in the admin area. How do I get it to watch and compile it? In the past I would add it to the manifest.json file and it would put it in to the ‘dist’ as .css ready for me to use.

Thanks

@patrickv what would be the ideal strategy to deal with optimizing and copying images from assets/images to dist/images ?