Customize Webpack configuration

Maybe time to switch to https://github.com/evanw/esbuild 100x faster.

I’m working on something that requires customizing the webpack config and adding a new entry point.

I’ve started looking into this, however the way frontity imports packages and settings is still not quite clear to me, is there a good place to start looking at? I have followed the code that merges the config and imports the main frontity.settings.ts but I’m missing some of the magic: i.e when and where frontity imports packages and its settings. Any FD or PR that you guys can point me to would be greatly appreciated.

I can show you that in a call if you want, and then we can publish the video here so it is helpful for the Feature Discussion itself.

What do you think?

Sure, that would be great!

Awesome. I’ll send you a message :slightly_smiling_face:

This is the meeting we had, with a summary of how the dev and build scripts generate the client and server bundles, and with an special emphasis on the Webpack configuration and how we thought packages should be able to extend that configuration.

It also has an explanation of a changes we plan to do: Instead of generating the all the client bundles for all the sites in a single Webpack run, use a single Webpack run for each site.

These are the drawings: Excalidraw | Hand-drawn look & feel • Collaborative • Secure

1 Like

@nicholasio.oliveira: could you please add a small explanation about the use case of Webpack extensibility that you need? Thanks! :slightly_smiling_face:

Hi there,

I need to add this to the webpack file

module: {
  rules: [
    {
      exclude: [/node_modules\/(?!(swiper|dom7)\/).*/, /\.test\.js(x)?$/],
      test: /\.js(x)?$/,
      use: [{ loader: 'babel-loader' }],
    }
  ],
}

Could you please point me to the right direction?

Thanks,
Jeff

Hey @jeffceirello :wave:

This is the webpack file that contains the module definition: frontity/modules.ts at dev · frontity/frontity · GitHub

You can patch it using patch-package - npm if you want.

I’ve started looking into this and recorded a small video to get some early feedback.

1 Like

I love it! :heart::grinning_face_with_smiling_eyes:

My only feedback would be to use a named export in the frontity.config.js file, to be able to add more stuff in the future:

// frontity.config.js
export const webpack = ({ ... }) => ...

Other than that, it looks great!

By the way, we also had a FD to customize babel configuration (Customize Babel configuration). But maybe we can close that for now, because configuring Babel will be possible using this:

// frontity.config.js
export const webpack = ({ config }) => {
  const babel = config.module.rules.find(
    (rule) => rule.use.loader === "babel-loader"
  ).options;

  // Add a new plugin.
  babel.plugins.push("my-own-babel-plugin");
};

The other option would be to get the frontity.config files at this point: frontity/index.ts at dev · frontity/frontity · GitHub and run the babel config through an babel exports of the frontity.config.js files:

// frontity.config.js
export const babel = ({ config }) => {
  // Add a new plugin.
  config.plugins.push("my-own-babel-plugin");
};

Then, pass the babel config to getWebpack() and run the webpack config through the webpack exports of the frontity.config.js files.

What do you think?

Another question that comes to my mind is if we should pass target as a parameter of the function, or pass a config object with all targets:

export const webpack = ({ config, target }) => {
  // Add something only on the server.
  if (target === "server") {
    config.someConfig = "...";
  }

  // Add something only on the client.
  if (target !== "server") {
    config.someOtherConfig = "...";
  }
};
export const webpack = ({ config }) => {
  // Add something only on the server.
  config.server.someConfig = "...";
  // Add something only on the client.
  config.module.someOtherConfig = "...";
  config.es5.someOtherConfig = "...";
};

Same for babel (if we add it).

EDIT: Nevermind, passing target as a function argument as you did seems much nicer.

Oh you are right! That’s a good call.

Indeed, that’s doable. Wondering how often would someone need to only adjust the babel configuration and not the whole config? :thinking: On the flip side, having to walk the webpack config only to get to the babel loader it’s painful. Gonna test it out.

One more thing I was meaning to ask is that currently how I thought about it, is that only the configuration files from within packages are read and apply. Should we allow a site specific configuration as well? Meaning:

/packages
/packages/theme/[...]
/packages/theme/frontity.config.ts # <--This is allowed and works
[...]
/frontity.settings.ts
/frontity.config.ts  # <-- Should we allow this?

What are your thoughts?

Recorded another video about it Loom | Free Screen & Video Recording Software

When I first thought about the frontity.config.js file, I thought that a site/root one would be cool, but right now I can’t think of any configuration that it is not better done at a package-level.

So to avoid confusion and anti-patterns, I would not include it at first. If we discover a real need for it later, we can always add it :slightly_smiling_face:

1 Like

By the way, for context, @cristianbote has started a PR to add this feature: Custom webpack config by cristianbote · Pull Request #812 · frontity/frontity · GitHub

I mentioned there this:

If we include the frontity configuration as well, as you showed in the video, we can create a package @frontity/vercel that uses the new .vercel_build_output folder for the build if process.env.VERCEL exists.

Another thing we want to add later to the frontity.config.js file is the ability to modify the site settings and add a package priority.

For example, the @frontity/amp package could set mode: "amp" automatically using this:

// High priority, run before any other package.
export const priority = 1

// Set the mode to "amp" so the user doesn't have to.
export const settings = ({ settings }) => {
  settings.mode = "amp";
}

So definitely it’s a good idea to use named exports :slightly_smiling_face::clap:

The PR is now merged :tada::tada:

3 Likes

I would like to test it first and decide after that. If it’s simple maybe with a CodeSandbox it’s enough. I will let you know.

1 Like

I can surely try! :smiley:

1 Like