Building css in webpack
Updated at: May 18, 2021
Prerequisites:​
- remove node_modules directory
- make sure u are running node v12
- run
npm install
Overview​
- All css from
app/assets/stylesheetsmoved toapp/javascript/stylesheets.app/assets/fontsalso moved toapp/javascript/fonts. - Asset pipeline is no more used and all css is being handled by webpack.
NOTE: After these changes build time became slower to 38 mins on average (proly due to differences of webpack vs sprokets), so some optimizations were implemented to compensate that (from 38 mins back to 10 mins avg)
3. Extracted some common styles into style_packs to improve webpack build time
5. npm install and webpack build happens out of docker, we only copy assets into final image, which decreases image size
6. Added caching to aws s3 during deploy, which helps build faster as well
How it works?​
In webpack we have term called "entry", in official docs it is stated:
An entry point indicates which module webpack should use to begin building out its internal dependency graph. webpack will figure out which other modules and libraries that entry point depends on (directly and indirectly).
Read more here: https://webpack.js.org/concepts/entry-points/
In our project all files under /app/javascript/packs are entry points. We call them packs. When each pack is being built by webpack it includes all neccessary js code in it and you include that pack in haml like this:
= javascript_pack_tag 'pages/users-show'
In users-show or its dependencies you can include css like this:
# users-show.jsx
import '@/../stylesheets/pages/users-show';
# accessing vendor in scss files
@import '../../../vendor/stylesheets/fullcalendar.min';
# or like this
require('@/../stylesheets/apps/standalone/aboutUs.css.scss');
NOTE: for some reason @ was not working always, so mostly i used relative path (which is not good), but it is a topic for future tasks 🤣.
NOTE: there is no need calling your css file in old format like aboutUs.css.scss (Rails way), you can call them like aboutUs.scss and import like this:
# note that you dont need to provide extension in import (scss part)
# .css is actually part of name
import 'path-to-file/aboutUs'
But if file is named with .css.scss format in it, then u import css like this
import 'path-to-file/aboutUs.css'
All css that was imported in a pack will be extracted into seperate file which will have same name as pack, so you include that css like this:
- content_for(:stylesheet_override) do
= stylesheet_pack_tag "pages/users-show"
NOTE: if pack is in a subdirectory of javascripts/packs, you use full path to that pack as in above users-show example.
You will see style_packs/ direcory which holds some common styles extracted.
Since now all css is build by webpack, which is pretty compute intensive (your mac will go hot), building whole project locally is not a good idea (in the past we were only building js, and css was directly pulled by asset pipeline rails), I suggest using optimization.js all the time. But u can build everything if u r lazy, with the cache in plase builds will take about 1 min.
Below is my updated optimization.js, investigate code and notice that u can build multiple apps at the same time, and also u can choose platforms as well. You will need to manually pick what modules and pages you want to build. Below is my optimization.js file, it might miss some module that u had in yours, if so, simply add yours into updated one.
You can run npm run show_packs to print all possible js packs into config/webpack/packs.txt file.
optimization.js:
const ALL_APPS = [
'aboutUs',
'booking',
'button',
'campaignBuilder',
'chat',
'comments',
'countdownTimer',
'ecommerce',
'faq',
'fileEmbed',
'formBuilder',
'graph',
'hitCounter',
'jobBoard',
'map',
'menu',
'microblog',
'multiSlider',
'musicPlayer',
'notificationBar',
'paypalButton',
'photoEditor',
'planComparison',
'popup',
'resume',
'scrollToTop',
'socialFeed',
'socialMediaIcons',
'tabs',
'test',
'twitterFeed',
'vote',
'weather',
];
// pass any extra packs from packs.txt you need
const MODULES = [
'project_updates-index',
'project_updates-new'
];
// Please choose apps from ALL_APPS array, please restart your webpack after changing it
const CHOSEN_APPS = ['formBuilder'];
const neededModules = [
'style_packs/ie9-overrides',
'style_packs/views',
'style_packs/powr_settings',
'style_packs/wix_settings',
'_admin_default',
'admin-index',
'wix_mini_market',
'application-static',
'apps-settings',
'apps-standalone',
'apps-view',
'cached_pages',
'users-account',
'users-show',
'static-home',
...CHOSEN_APPS.map(app => `apps/${app}`), // standalone
...CHOSEN_APPS.map(app => `apps/views/${app}`),
// ...CHOSEN_APPS.map(app => `apps/settings/powr/${app}`),
// ...CHOSEN_APPS.map(app => `apps/settings/weebly/${app}`),
// ...CHOSEN_APPS.map(app => `apps/settings/wix/${app}`),
...MODULES.map(m => m),
];
if (CHOSEN_APPS.includes('formBuilder')) {
neededModules.push('powrzilla-editor', 'powrzilla-templates');
}
const result = neededModules;
// const result = 'all';
module.exports = result;