Dev server doesn't respect Drupal's CSS organization (SMACSS)

Created on 19 August 2024, 12 months ago

Problem/Motivation

Stylesheets in Drupal follow a specific file organization, the SMACSS-style categorization of its CSS rules β†’ . This works with production builds where CSS assets are loaded as CSS files using <link rel="stylesheet">, but not with Vite dev server which loads CSS assets as JavaScript code that injects the CSS into the page. The order of the CSS styles can be incorrect. In my case a base style of a custom Drupal library gets loaded after the component styles of my theme, overriding the theme rules.

Steps to reproduce

Setup a Drupal site with a custom Drupal module and custom Drupal theme both using Vite (see 3349311#comment-15657697 πŸ“Œ Example configurations/starting points Active for details about my exact setup), maybe just a theme could do it as well.

In the module create a library:

typography:
  css:
    base:
      src/css/typography.css: { }

In the theme create a library

global_styles:
  css:
    component:
      src/css/style.css: { }

and load both libraries globally:

libraries:
  - my_module/typography
  - my_theme/global_styles

In the typography.css add

h1 {
  color: red;
  font-size: 10px;
}

and in the style.css add

h1 {
  color: green;
  font-size: 36px;
}

In my case, the H1 is small and red while it should be large and green (component styles must override base styles according to SMACSS).

I'm not sure whether this is an issue of the Drupal Vite module or Vite itself.

πŸ› Bug report
Status

Active

Version

1.2

Component

Code

Created by

πŸ‡¦πŸ‡ΉAustria mvonfrie

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @mvonfrie
  • πŸ‡¦πŸ‡ΉAustria mvonfrie

    Addition: I had this problem already with 1.1.3 but just updated to 1.2.1 to check if it is still there.

  • πŸ‡ΊπŸ‡ΈUnited States mortona2k Seattle

    I think I have been working around this by writing component code with more specific selectors.

    But I have had all kinds of problems with this as well. I don't know how to get around it because vite doesn't know about drupal's library layers and weights.

    If you load stylesheets into a main js file, you can specify the order, but that will bundle them all together.

    Maybe it makes sense to bundle them and load in the theme layer? Or component for modules?

    Maybe use @layers to specify the order, however these will precede all drupal libraries in the cascade.

  • First commit to issue fork.
  • Pipeline finished with Failed
    3 months ago
    Total: 215s
    #495064
  • MR !26 should fix this issue.
    I found that Vite could use existing style tags instead of adding new ones at the end of the head tag. We only need to render the <style> tag in the place according to SMACSS with the correct data-vite-dev-id attribute.
    By default, data-vite-dev-id is the absolute path to the file, as in the environment where Vite's dev-server is running.
    So, in case PHP and Node are in different environments (e.g. in different Docker containers), I've added the devServerRootAbsolutePath option to specify the path. By default, it will be the path as in the PHP environment.

  • Pipeline finished with Failed
    3 months ago
    Total: 170s
    #495085
  • Pipeline finished with Failed
    3 months ago
    Total: 350s
    #495088
  • Pipeline finished with Success
    3 months ago
    Total: 157s
    #495097
  • Status changed to Needs review 11 days ago
  • πŸ‡ΊπŸ‡ΈUnited States mortona2k Seattle

    Here's what I'm seeing without the patch:

    Without dev mode (all libraries in header):

    <head>
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/unocss.css?szv5so" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/base.css?szv5so" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/layout.css?szv5so" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/progress.css?szv5so" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/messages.css?szv5so" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/branding.css?szv5so" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/page.css?szv5so" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/page_footer.css?szv5so" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/page_header.css?szv5so" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/page_main.css?szv5so" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/responsive_menu.css?szv5so" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/responsive_menu_toggle.css?szv5so" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/component.css?szv5so" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/node.css?szv5so" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/toolbar.css?szv5so" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/prism.css?szv5so" />
    </head>

    With dev mode (Initially loads in footer, then injects into header):

    <body>
    <script src="https://mantra.ddev.site:5173/components/branding/branding.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/components/layout/page/page.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/components/layout/page/page_footer/page_footer.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/components/layout/page/page_header/page_header.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/components/layout/page/page_main/page_main.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/components/responsive_menu/responsive_menu.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/components/responsive_menu/responsive_menu_toggle/responsive_menu_toggle.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/components/responsive_menu/responsive_menu_toggle/responsive_menu_toggle.js" type="module"></script>
    ...
    <script src="https://mantra.ddev.site:5173/libraries/global/base.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/libraries/global/layout.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/libraries/global/component.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/libraries/drupal/node.css" type="module"></script>
    </body>

    And with the patch:

    With dev mode:

    <head>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/libraries/unocss/unocss.css"></style>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/libraries/global/base.css"></style>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/libraries/global/layout.css"></style>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/libraries/drupal/progress.css"></style>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/libraries/drupal/messages.css"></style>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/components/branding/branding.css"></style>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/components/layout/page/page.css"></style>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/components/layout/page/page_footer/page_footer.css"></style>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/components/layout/page/page_header/page_header.css"></style>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/components/layout/page/page_main/page_main.css"></style>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/components/responsive_menu/responsive_menu.css"></style>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/components/responsive_menu/responsive_menu_toggle/responsive_menu_toggle.css"></style>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/libraries/global/component.css"></style>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/libraries/drupal/node.css"></style>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/libraries/drupal/toolbar.theme.css"></style>
    <style type="text/css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/libraries/modules/prism.theme.css"></style>
    </head>
    <body>
    <script src="https://mantra.ddev.site:5173/libraries/unocss/unocss.css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/libraries/unocss/unocss.css" type="module"></script>
    ...
    <script src="https://mantra.ddev.site:5173/components/branding/branding.css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/components/branding/branding.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/components/layout/page/page.css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/components/layout/page/page.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/components/layout/page/page_footer/page_footer.css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/components/layout/page/page_footer/page_footer.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/components/layout/page/page_header/page_header.css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/components/layout/page/page_header/page_header.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/components/layout/page/page_main/page_main.css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/components/layout/page/page_main/page_main.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/components/responsive_menu/responsive_menu.css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/components/responsive_menu/responsive_menu.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/components/responsive_menu/responsive_menu_toggle/responsive_menu_toggle.css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/components/responsive_menu/responsive_menu_toggle/responsive_menu_toggle.css" type="module"></script>
    ...
    <script src="https://mantra.ddev.site:5173/libraries/global/base.css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/libraries/global/base.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/libraries/global/layout.css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/libraries/global/layout.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/libraries/global/component.css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/libraries/global/component.css" type="module"></script>
    <script src="https://mantra.ddev.site:5173/libraries/drupal/node.css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/libraries/drupal/node.css" type="module"></script>
    <script src="/libraries/prism/prism.js?v=10.5.1"></script>
    <script src="https://mantra.ddev.site:5173/libraries/modules/prism.theme.css" data-vite-dev-id="/var/www/html/web/themes/custom/mantra_starter/libraries/modules/prism.theme.css" type="module"></script>
    </body>

    Without dev mode (same?):

    <head>
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/unocss.css?szv5wu" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/base.css?szv5wu" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/layout.css?szv5wu" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/progress.css?szv5wu" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/messages.css?szv5wu" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/branding.css?szv5wu" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/page.css?szv5wu" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/page_footer.css?szv5wu" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/page_header.css?szv5wu" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/page_main.css?szv5wu" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/responsive_menu.css?szv5wu" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/responsive_menu_toggle.css?szv5wu" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/component.css?szv5wu" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/node.css?szv5wu" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/toolbar.css?szv5wu" />
    <link rel="stylesheet" media="all" href="/themes/custom/mantra_starter/dist/prism.css?szv5wu" />
    </head>
  • πŸ‡ΊπŸ‡ΈUnited States mortona2k Seattle

    It looks like the order of libraries is fixed in the head for dev mode, but not the body.

    Without the patch, it looks like my theme libraries are loaded in the body after component libraries.

    With the patch, the styles in the head appear to be in the correct order, matching build mode.
    The body styles are the same as without the patch, although they are different I think.

    Seems to be working.

Production build 0.71.5 2024