alexgm
January 20, 2025, 10:18pm
1
Hi everyone,
I’m having an issue with my Sage setup (using Bud.js for asset bundling) where my JavaScript modules are initializing before Webpack-inlined styles are fully applied on the first page load. This causes problems when my modules depend on accurate DOM dimensions (e.g., calculating heights or applying animations).
My Setup:
Framework: Sage 10 + Acorn v4
Build Tool: Bud.js
*** Scss ***
The Problem:
On the first page load , Webpack dynamically injects styles into <style>
tags, but my JavaScript modules (e.g., StickyHeader, Swiper) are initialized before those styles are fully applied. As a result:
My DOM dimensions are inaccurate when calculated in the modules.
Styles appear to be applied after the modules have already initialized.
What I’m Looking For:
I want to ensure that my JavaScript modules are initialized only after Webpack has fully injected and applied styles during the initial page load in development mode. Is there a reliable way to hook into Webpack or Bud.js to detect when the styles are applied?
alexgm
January 21, 2025, 1:43am
3
Hi @ben ,
Here is a empty boilerplate of whats look like my app.js
import domReady from '@roots/sage/client/dom-ready';
import Swiper from './app/Swiper';
import StickyHeader from './app/StickyHeader';
/**
* Active modules
*/
const ActiveModules = {
Swiper,
StickyHeader,
};
/**
* Initialize all modules
*/
const initializeModules = () => {
for (const [key, module] of Object.entries(ActiveModules)) {
if (!module.init) {
console.warn(`Module ${key} is missing the init method`);
continue;
}
module.init();
}
};
/**
* Application entrypoint
*/
domReady(() => {
// Initialize all modules
initializeModules();
});
const hmr = import.meta.webpackHot;
if (hmr) {
hmr.accept(console.error);
}
Here is my bud.config.js
import globImporter from 'node-sass-glob-importer';
import fs from 'fs';
import ThemeConfig from './theme.config.js';
import ExtractEditorRules from './resources/scripts/postcss-extract-editor.js';
import path from 'path';
const __CUR_DIR__ = fs.realpathSync('.').split('/').pop();
/**
* Compiler configuration
*
* @see {@link https://roots.io/sage/docs sage documentation}
* @see {@link https://bud.js.org/learn/config bud.js configuration guide}
*
* @type {import('@roots/bud').Config}
*/
export default async (bud) =>
{
/**
* Development settings
*/
bud.when(bud.isDevelopment, () =>
{
bud.devtool('source-map');
bud.postcss.setSourceMap(true);
});
/**
* Production settings
*/
bud.when(bud.isProduction, () =>
{
bud.devtool(false);
bud.minimize();
});
/**
* Add our custom PostCSS plugin for extracting `@editor` rules into a separate css file.
*/
bud.postcss.setPlugin(
'extract-editor',
ExtractEditorRules({
outputFile: bud.path('editor-rules.css'),
})
);
bud.postcss.use(plugins => [...plugins, 'extract-editor']);
/**
* Add sass glob importer
*/
bud.tap(bud =>
{
/** @ts-ignore */
bud.build.items.sass.setOptions(
{
sourceMap: true,
sassOptions: {
importer: globImporter(),
silenceDeprecations: ['legacy-js-api'],
}
}
)
});
/**
* Add svg source asset module
*
* @see {@link https://webpack.js.org/guides/asset-modules/}
*/
bud.hooks.on(`build.module.rules.oneOf`, (rules = []) =>
{
rules.push({
test: /\.svg$/,
resourceQuery: (/source/),
type: 'asset/source'
})
return rules
})
/**
* Add svgr/webpack loader
* @see {@link https://react-svgr.com/docs/webpack/}
*/
bud.hooks.on(`build.module.rules.oneOf`, (rules = []) =>
{
rules.unshift({
test: /\.svg$/,
issuer: /\.[jt]sx?$/, // Matches JavaScript or TypeScript files
use: [
{
loader: `@svgr/webpack`,
options: {
// icon: true,
},
},
],
});
return rules;
});
// We need to set the issuer for the inline-svg and svg rules to avoid conflicts with the svgr loader
bud.build.rules.svg.setIssuer(/^(?!.*\.(js|ts|jsx)$).*$/);
bud.build.rules['inline-svg'].setIssuer(/^(?!.*\.(js|ts|jsx)$).*$/);
/**
* Application assets & entrypoints
*
* @see {@link https://bud.js.org/reference/bud.entry}
* @see {@link https://bud.js.org/reference/bud.assets}
*/
bud
.entry('app', ['@scripts/app', '@styles/app'])
.entry('editor', ['@scripts/editor', '@styles/editor'])
.assets(['images', 'fonts']);
/**
* Exclude external wp dependencies
* @see {@link https://bud.js.org/extensions/bud-preset-wordpress#excluding-dependencies}
*/
bud.wp.setExclude([
'lodash',
]);
/**
* Set public path
*
* @see {@link https://bud.js.org/reference/bud.setPublicPath}
*/
bud.setPublicPath(`/wp-content/themes/${__CUR_DIR__}/public/`);
/**
* Add aliases
*
* @see {@link https://bud.js.org/reference/bud.alias}
*/
bud.alias('@node', fs.realpathSync('node_modules'));
bud.alias('@vendor', fs.realpathSync('vendor'));
/**
* Development server settings
*
* @see {@link https://bud.js.org/reference/bud.setUrl}
* @see {@link https://bud.js.org/reference/bud.setProxyUrl}
* @see {@link https://bud.js.org/reference/bud.watch}
*/
bud
.setUrl('http://localhost:3005')
.setProxyUrl('http://localhost/')
.watch(['resources/views', 'resources/scripts', 'app'], {
usePolling: false,
});
/**
* Theme configuration
*/
bud.wpjson
.setSettings(ThemeConfig.wpSettings)
.setStyles(ThemeConfig.wpStyles)
.useTailwindColors()
.useTailwindFontFamily()
.useTailwindFontSize()
.useTailwindSpacing();
};
ben
January 21, 2025, 9:54am
4
That’s a lot. Post a minimal reproduction.
alexgm
January 21, 2025, 4:24pm
6
Hi @Ben ,
That’s a lot. Post a minimal reproduction
I’m not sure where the problem lies, so I can’t be more specific. Since the bundling process is quite complex, I’ve shared all the relevant code. The bud.config.js file is a particularly important piece, which is why I included it in its entirety.
Thanks for your support and time !