Bundling
Content
HTML, CSS and Assets
Html, scss and assets files that are in the project folder are copiyng using a "CopyWebpackPlugin" plugin. Also, bundle process is mutating html files by adding scripts with special attribute "data-server-only" that indicated about data that needs to be processed in SSR and removed for CSR.
This part of webpack config is written in ./webpack.common.js
plugins: [
new CopyWebpackPlugin({
patterns: [
/* COPYING ALL IMAGES */
{
from: 'assets/images',
to: 'assets/images',
context: 'src/',
noErrorOnMissing: true
},
/* COPYING CSS FILES */
{
from: 'assets/css/**/*.css',
to: '[path][name].css',
context: 'src/'
},
/* COPYING ALL HTML FILES */
{
from: '**/*.html',
to: '[path][name].html',
context: 'src/',
filter: (resourcePath) => {
return !resourcePath.includes('/assets/');
},
transform: (content, resourcePath) => {
return new Promise(resolve => {
let string = content.toString();
let data = string.split('<body>');
let modified = data[0] + '<body><script data-server-only src="https://unpkg.com/@gudhub/core@1.2.0/umd/library.min.js"></script><script data-server-only src="https://unpkg.com/@gudhub/gh-component/dist/main.js"></script>' + data[1];
data = modified.split('<head>');
modified = data[0] + '<head><script id="base_write_script">document.write(`<base href="${window.MODE === \'production\' ? \'https\' : \'http\'}://${window.getConfig().website}">`);document.querySelector("#base_write_script").remove();</script>' + data[1];
data = modified.split('</body>');
modified = data[0] + '<script data-server-only src="/assets/js/bundle.js"></script></body>' + data[1];
resolve(Buffer.from(modified, 'utf-8'));
});
}
},
/* COPYING ROBOTS.TXT */
{
from: 'robots.txt',
to: 'robots.txt',
context: 'src/'
},
/* COPYING FAVICON */
{
from: 'favicon.ico',
to: 'favicon.ico',
context: 'src'
}
]
}),
new MiniCssExtractPlugin({
filename: '[name].css'
}),
new GenerateJsonFromJsPlugin({
path: 'config.mjs',
filename: 'config.json'
})
]
Also we have handwritten plugin "GenerateJsonFromJsPlugin", his response is to convert "./config.mjs" to JSON file.
You can modify this file if you need additional files to bundle.
Components bundling
Components can be bundled in 2 ways:
-
all in one
: all components are combined into a singlebundle.js
andbundle.css
file. This bundle is need for puppeteer work;Code responsible for that located in
./webpack.bundle.js
:export default { /* BUNDLING WEBCOMPONENTS */ entry: () => { const entries = glob.sync('./src/assets/js/components/**/*.js'); // adds "node_modules/@gudhub/ssg-web-components-library" entries const gudhubEntries = (() => { const entries = []; for (const componentConfig of GudhubComponents) { entries.push('./node_modules/' + componentConfig.src); } return entries; })() return [ ...entries, ...gudhubEntries ]; }, output: { path: path.resolve('dist/assets/js'), filename: "bundle.js" }, module: { rules: [ { test: /\.html$/i, loader: 'html-loader', options: { minimize: false, sources: false } }, { test: /\.(s(a|c)ss)$/, use: [ { loader: MiniCssExtractPlugin.loader }, { loader: 'css-loader', options: { url: false } }, 'sass-loader' ] } ] }, plugins: [ new MiniCssExtractPlugin({ filename: 'bundle.css' }) ] }
-
separately
: each component collects js and css files into a separate folder named as a component. This need for puppeteer to make bundle with components for page;Code responsible for that located in
./webpack.common.js
:export default { ... /* BUNDLING WEBCOMPONENTS */ entry: () => { const entries = glob.sync('./src/assets/js/**/*.js').reduce((obj, el) => { obj[el.replace('src/', '')] = el; return obj; }, {}); // adds entries from @gudhub/ssg-web-components-library const gudhubEntries = (() => { const entries = []; for (const componentConfig of GudhubComponents) { entries.push('./node_modules/' + componentConfig.src); } return entries.reduce((obj, el) => { const path = el; const componentsIndex = path.indexOf('/components'); obj[path.replace(path.substring(0, componentsIndex), '/assets/js/')] = el; return obj; }, {}); })() return { ...entries, ...gudhubEntries }; }, output: { path: path.resolve('dist'), filename: "[name]", }, module: { rules: [ { test: /\.html$/i, loader: 'html-loader', options: { minimize: false, sources: false } }, { test: /\.(s(a|c)ss)$/, use: [ { loader: MiniCssExtractPlugin.loader }, { loader: 'css-loader', options: { url: false } }, 'sass-loader' ], } ] } }