Applying PostCSS Plugin to only editor CSS

Hey guys!

I’m trying to apply the PostCSS plugin ‘postcss-editor-styles’ to the editor styles only, however it seems to be applying both app.css and editor.css, breaking the pages styling.

Here’s the relevant part of my buds configuration regarding this issue.

config

    .entry({
    editor: ['scripts/editor.js', 'styles/editor.css'],
    }).tap(bud => {

      bud.postcss.setPlugin('postcss-editor-styles', [
        require.resolve('postcss-editor-styles'), // the plugin module path
        {}, // options
      ])
    })
    .assets([])

    /**
     * Application entrypoints
     *
     * Paths are relative to your resources directory
     */
     .entry({
      app: ['scripts/app.js', 'styles/app.css'],
    })

Any help would be greatly appreciated

1 Like

Related:

The way you would do this is by setting up bud in a multi-compiler configuration. I don’t have time right this moment but I will post a config that can get you started as soon as I have a little extra time.

2 Likes

Hi @kellymears ,

Also using plugin postcss-editor-styles for a great setup with tailwindcss @import styles and .editor-styles-wrapper “scoping” in Gutenberg (it was working great with laravel-mix with multiple $entry config).

I looked at Running multiple compilers | bud.js and, as a poor js dev, i’m a bit lost … if you have some advice or :boom: start-config it would be great.

the idea is to require('postcss-editor-styles) config only for “editor.css” bud.entry() , maybe with a hook or as you suggested with multi-compilers-config ?

Old mix config for editor.css was

thanks for your feedback and above all for your great job on Bud !! that’s amazing.
Cheers.

Thanks!

First off, I think this post by @strarsis might be of interest to you:

https://discourse.roots.io/t/absolute-domain-relative-path-for-asset-urls-in-css/

I’m not 100% but it seems like it is probably related. You might not need to use multiple compilers!

That said, here’s how you would do it as it was asked:

There are some important fixes included in 5.8.3. You should upgrade @roots/bud, @roots/sage and @roots/bud-tailwindcss to that version.

To reiterate the problem as I understand it. We have a config and we want to apply a postcss plugin exclusively to the editor entrypoint:

module.exports = async bud => 
  bud.entry({
    app: ['@scripts/app', '@styles/app'],
    editor: ['@scripts/editor', '@styles/editor'],
  })

In bud.js we do that with bud.make. This function basically creates a new instance of bud and allows you to configure it separately. So, we’ll split our entrypoints into two compilations:

module.exports = async bud =>
  bud.make("frontend", async (frontend) =>
      frontend
        .setPath("@dist", "public/app")
        .entry("app", ["@scripts/app", "@styles/app"])
  )

  .make("editor", async (editor) =>
      editor
        .setPath("@dist", "public/editor")
        .entry("app", ["@scripts/editor", "@styles/editor"])
  )

The function we’re passing to bud.make can be thought of as its own bud config file, if that’s helpful.

It is important that we give each compiler it’s own distribution directory (@dist) because otherwise they will overwrite one another.

Now, the only thing left to do is apply the postcss configuration to "editor":

module.exports = async bud =>
  bud.make("frontend", async (frontend) =>
      frontend
        .setPath("@dist", "public/app")
        .entry("app", ["@scripts/app", "@styles/app"])
  )

  .make("editor", async (editor) =>
      editor
        .setPath("@dist", "public/editor")
        .entry("app", ["@scripts/editor", "@styles/editor"])

        /** postcss config applies only to editor */
        .postcss.setPlugin("postcss-editor-styles", [
          require.resolve("postcss-editor-styles"),
          {scopeTo: "#editor .editor-styles-wrapper"},
        ])
  )

See the docs on @roots/bud-postcss for more information on customizing postcss.

This was my final config when I was testing:

module.exports = async bud => {
  bud
    /**
     * Frontend css/js
     *
     * @param {bud} app
     */
    .make("frontend", async frontend =>
      frontend
        .setPath("@dist", "public/app")
        .entry("app", ["@scripts/app", "@styles/app"])
    )

    /**
     * Editor css/js
     *
     * @param {bud} editor
     */
    .make("editor", async editor =>
      editor
        .setPath("@dist", "public/editor")
        .entry("editor", ["@styles/app"])
        .postcss.setPlugin("postcss-editor-styles", [
          require.resolve("postcss-editor-styles"),
          {
            scopeTo: "#editor .editor-styles-wrapper",
          },
        ])
    )

    .proxy("http://example.test")
    .serve("http://localhost:3000")
    .watch("resources/views/**/*", "app/**/*");
};

Some final notes:

  1. When you use multiple compilers anything like .entry and .setPath in the outer scope (not in a bud.make call) will be ignored. The only thing you want to do in the outer scope is configure the dev server (bud.proxy, bud.serve, bud.watch, etc.)

  2. You can run a specific compiler with the --target flag. So, if you’re only working on frontend styles you don’t need to compile the editor assets: bud build --target frontend

  3. You will generate two manifests using this approach and will need to set that up using Acorn in setup.php.

4 Likes

Hi Kelly,

I’m so sorry for my late reply, a lot of work in this pre-summer period.

But… wow! Thank you very much for the great explanations and the proposed solution, it seems exactly what I need, I will test it right away and I will report back. Besides, I now understand better how Bud works :wink:

Thanks also for the link from @starsis, I’ll take a look too.

I wish you a nice summer.

Thanks for this!

How exactly would you do this?

I got 2 folders in my public directory now, app & editor, each with it’s own manifest.json.
But how can I tell the Roots\bundle function to use the separate manifest files in setup.php:

add_action('wp_enqueue_scripts', function () {
	bundle('app')->enqueue();
}, 100);

add_action('enqueue_block_editor_assets', function () {
	bundle('editor')->enqueue();
}, 100);

What I tried so far (looking at the Roots\bundle function):

bundle('app', 'app.manifest')->enqueue();
bundle('editor', 'editor.manifest')->enqueue();

But that results in the following error:

Undefined array key "editor.manifest"

Any examples out there?
Thanks!

I found where I should alter this, I changed this in my config/assets.php:

'default' => 'app',
'manifests' => [
		'app' => [
			'path' => get_theme_file_path('public/app'),
			'url' => get_theme_file_uri('public/app'),
			'assets' => get_theme_file_path('public/app/manifest.json'),
			'bundles' => get_theme_file_path('public/app/entrypoints.json'),
		],
		'editor' => [
			'path' => get_theme_file_path('public/editor'),
			'url' => get_theme_file_uri('public/editor'),
			'assets' => get_theme_file_path('public/editor/manifest.json'),
			'bundles' => get_theme_file_path('public/editor/entrypoints.json'),
		]
	]

Then I can simply use:

bundle('app')->enqueue();
bundle('editor', 'editor')->enqueue();