I've got the following webpack configuration that traverses multiple PHP packages, looks for .js
and .scss
files in their respective /resources
directory, builds them and puts them into the /out/src
directory of the module. This allows me to write modern ES6 belonging to a package without creating a webpack config for it. When in watch mode, it has to be restarted if I add a new file but otherwise it is working out great.
const getEntries = () => {
let js = glob.sync("./vendor/myvendor/**/resources/**/!(node_modules)/**/*.js");
let css = glob.sync("./vendor/myvendor/**/resources/**/!(node_modules)/**/*.scss");
if (js.length === 0 && css.length === 0) {
return "./noop.js";
}
let entries = {};
for (let i = 0; i < js.length; i++) {
const p = js[i];
const outPath = p.replace("/resources/", "/out/src/");
entries[outPath] = p;
}
for (let i = 0; i < css.length; i++) {
const p = css[i];
const outPath = p.replace("/resources/", "/out/src/").replace(".scss", "");
entries[outPath] = p;
}
return entries;
};
module.exports = {
mode: "production",
entry: getEntries(),
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
// Compiles Sass to CSS
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader",
],
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: [["@babel/preset-env", { debug: true, useBuiltIns: "usage", corejs: 3 }]],
plugins: [["@babel/plugin-transform-runtime", { corejs: 3 }]],
},
},
},
],
},
output: { path: __dirname, filename: "[name]" },
plugins: [new MiniCssExtractPlugin()],
watchOptions: {
ignored: ["node_modules", "**/Tests/**"],
},
};
There are some caveats regarding file size, however: I have to add polyfills with corejs so the generated code works in older browsers and it looks like webpack is adding the necessary polyfills per file, so many of them are included multiple times. Also, webpack is bundling each file with its module wrapper code so it can be executed on its own.
So here are my questions:
- is it possible to build one js file with polyfills that is included in all pages so they are no longer included in each file but also keep the "usage" param so only used features are polyfilled?
- can I make this central dependency also be the only one that includes the webpack module wrapper code to save even more on filesize? The other javascript files are included in PHP templates dynamically (and most scripts are only used on few pages) so building a huge chunked bundle containing everything is not a good option.
EDIT: after trying out the answer below, the entry looks like this:
{
'./vendor/myVendor/myModule0/out/src/js/countdown.js': {
import: './vendor/myVendor/myModule0/resources/js/countdown.js',
dependOn: 'polyfills.min.js'
},
'./vendor/myVendor/myModule0/out/src/js/paymentSelect.js': {
import: './vendor/myVendor/myModule0/resources/js/paymentSelect.js',
dependOn: 'polyfills.min.js'
},
'./vendor/myVendor/myModule0/out/src/js/shippingAddressSelect.js': {
import: './vendor/myVendor/myModule0/resources/js/shippingAddressSelect.js',
dependOn: 'polyfills.min.js'
},
'./vendor/myVendor/myModule0/out/src/js/modal.js': {
import: './vendor/myVendor/myModule0/resources/js/modal.js',
dependOn: 'polyfills.min.js'
},
'./vendor/myVendor/oxid-factfinder-extends/out/src/js/custom.js': {
import: './vendor/myVendor/oxid-factfinder-extends/resources/js/custom.js',
dependOn: 'polyfills.min.js'
},
'./vendor/myVendor/oxid-faq/out/src/js/faqForm.js': {
import: './vendor/myVendor/oxid-faq/resources/js/faqForm.js',
dependOn: 'polyfills.min.js'
},
'./vendor/myVendor/oxid-klarna-extends/out/src/js/payments_handler.js': {
import: './vendor/myVendor/oxid-klarna-extends/resources/js/payments_handler.js',
dependOn: 'polyfills.min.js'
},
'./vendor/myVendor/oxid-mobile-menu/out/src/js/filter-drawer.js': {
import: './vendor/myVendor/oxid-mobile-menu/resources/js/filter-drawer.js',
dependOn: 'polyfills.min.js'
},
'./vendor/myVendor/oxid-mobile-menu/out/src/js/mobile-menu.js': {
import: './vendor/myVendor/oxid-mobile-menu/resources/js/mobile-menu.js',
dependOn: 'polyfills.min.js'
},
'./vendor/myVendor/oxid-storefinder/out/src/js/store_request.js': {
import: './vendor/myVendor/oxid-storefinder/resources/js/store_request.js',
dependOn: 'polyfills.min.js'
},
'polyfills.min.js': './polyfills.js'
}
(this is the return value of the modified getEntries function)
I added an empty polyfills.js
and included it in the individual js files with import '../../../../../polyfills';
at the top of each, yet the polyfills file stays at 202 bytes of filesize and the individual modules don't get smaller.