Problem/Motivation
Many site owners would like to be in control of the code they deliver. In this respect, some configuration steps are required to add NPM packages, create configuration file, and define the location of the destination CSS.
Steps to reproduce
Add NPM packages
npm install -D tailwindcss "@tailwindcss/forms" "@tailwindcss/typography" daisyui@beta autoprefixer postcss "@tailwindcss/postcss" postcss-import postcss-nested cssnano
Create two script definitions in the `package.json` file
"scripts": {
"dev": "NODE_ENV=development postcss ./style/style.pcss.css -o ./dist/style.css -w -m",
"build": "NODE_ENV=production postcss ./style/style.pcss.css -o ./dist/style.css"
},
Configure PostCSS
Create a postcss.config.js file
module.exports = (ctx) => ({
map: ctx.options.map,
plugins: {
"postcss-import": {},
"postcss-nested": {},
"@tailwindcss/postcss": {},
autoprefixer: {},
...(process.env.NODE_ENV === "production"
? { cssnano: { preset: "default" } }
: {}),
},
});
Configure TailwindCSS and DaisyUI
- Create a folder /style, if it does not already exist
- Create the style.pcss.css file in the above folder with the following contents
@import "tailwindcss";
@plugin "@tailwindcss/typography";
@plugin "@tailwindcss/forms";
@plugin "daisyui";
Update Theme definition
- Update ui_suite_daisyui.info.yml
Remove reference to the following libraries
- ui_suite_daisyui/daisyui_cdn
- ui_suite_daisyui/daisyui_themes_cdn
- ui_suite_daisyui/custom_css
Add reference to the following library
- ui_suite_daisyui/daisyui
Update ui_suite_daisyui.libraries.yml
Add definition of the daisyui library
daisyui:
css:
theme:
dist/style.css: { minified: true }
Create destination for CSS
- Create a folder /dist, if it does not already exist
Create CSS
- npm run build - to build a compressed CSS file
- npm run dev - to build a non-compressed CSS file and watch for changes, and rebuild after change
Proposed resolution
Update configuration to cater for own built version CSS for eventual publication to production environments.
Remaining tasks
- Validate concept
- Ensure that the reference to DaisyUI 5 beta in the configuration, is updated as and when DaisyUI 5 is released
User interface changes
None
API changes
- Remove dependency on externally delivered CSS files
- Host code to automatically (re)generate CSS files
- Running npm update will download and make available most recent versions of TailwindCSS and DaisyUI and other libraries
- Running npm run build will rebuild CSS with the most recently installed versions of TailwindCSS and DaisyUI
Data model changes
none
Issue fork ui_suite_daisyui-3508143
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- ui_suite_daisyui-3508143-starterkit-cleanup
changes, plain diff MR !145
- ui_suite_daisyui-3508143-starterkit
changes, plain diff MR !138
- ui_suite_daisyui-3508143-starterkit-postcss
changes, plain diff MR !144
- 3508143-starterkit-followup
changes, plain diff MR !140 /
changes, plain diff MR !139
Comments
Comment #2
g4mbiniHello @paddy_deburca ,
One of the main goal of this theme is to promote display building and no-code mapping between data and design elements. So the main persona here is Site Builder.
It's important that this type of users who install the theme have directly a good visual experience and already built-in configs. That being said, I will keep the CDN libraries by default (and why not ship a DaisyUI CSS library already built that we can switch with theme settings).
Other users like developers, are for most them already confortable with build processes (SASS, Tailwind, ...) so I guess they know how to do that, right ?
IMHO, build process tools shouldn't be shipped inside the theme, but well documented instead, in the README or in the incoming htdocs.
Do you want to take care of that ?
Comment #3
g4mbiniComment #4
g4mbiniComment #5
paddy_deburca commentedMy proposal is to move this documentation to a starterkit theme. This would allow
- existing theme to work as-is and un modified
- create sub-theme from starterkit with documentation and examples on how to configure with own versions of CSS
There are multiple ways to build the local CSS, and of these I propose to only document two
- using TailwindCSS CLI to compile the CSS
- using PostCSS to compile the CSS with some processors
The file `package.json` is be required with a minimum configuration for TailwinsCSS, daisyUI, and TailwindCSS/CLI.
Two extra files _could_ also be included
- `package-postcss-example.json` - containing an example, working, configuration, with PostCSS, TailwindCSS, daisyUI
- `postcss-example.js` - containing PostCSS configuration
In both cases, we can include the script definitions to hide the complexity of `npm`/`npx` calls
- `npm run build` to build and store CSS in `output.css`
- `npm run dev` to build, and re-build on file updates, and store CSS in `output.css`
The `README.md` file documents these configuration items, but having a sample file(s) to start with would make process easier.
If this approach is OK, I will create the sample files, and create a merge request with the entire starterkit folder.
Comment #11
vasikenew MR available
https://git.drupalcode.org/project/ui_suite_daisyui/-/merge_requests/140
Which updates the previous one:
- Use the daisyUI logo/icon
- Delete the extra files that "needed renaming" - not actually needed
- Fix the Regions and libraries
- Remove not needed files ... empty or inherited from the base theme.
- Emptied generated CSS file.
- Update README file - simplify the process + remove older Drupal info.
I could generate an working theme just with
php core/scripts/drupal generate-theme my_daisyui_theme --starterkit ui_suite_daisyui_starterkit --path themes/customnpm installnpm run buildornpm run devcommands
Comment #12
vasikeComment #13
christian.wiedemann commentedHi all,
I checked some frameworks like nuxt and next and other themes. But from my point of view there is no best practice. So here are my 5 cents about the folder structure and compile steps.
1. CSS compile in the Drupal core way.
So I think we should do it like Drupal Core. Maybe other themes will follow. They use pcss.css as source files and generate the resulting file in the same folder without pcss.css extension. So I would change the src/css folder structure to:
So we don't have a dist folder. (Not 100% sure about this. But I think some CSS is in a dist folder and some not is not so clean)
To generate the CSS I would do something similar core is doing. Following Script is part of core. Maybe we can use it or we copy and adapt it. I think it is easy to adapt to tailwind CLI. It uses a glob to add each CSS to a separate process so there is no need to adopt an config file if a CSS file is added.
What do you think?
Style/lint
We should add some tailwind specific style and linting configs.
Blocks
Not realy have a hard opionion about it.
I think a vite startkit would be also nice. But this is a seperate issue.
Comment #14
paddy_deburca commentedI am inclined to agree with using the Drupal way - store custom CSS in *.pcss.css files and compile to an *.css file in the same folder. This changes the output folder, and possibly negates the need for a dist/ folder altogether.
The code sample provided could be very interesting - at the moment I miss the context in which this code is executed. Is this build process publicly available? Is it possible to see the environment in which it is run, so that I can see if we can cherry pick utilities from the process?
Comment #15
paddy_deburca commentedRegarding
Stylelint- we *could* includestylelintinto the build process.By defining lints in a config file
we can invoke the
stylelintplugin during the build process.An invalid CSS such as
would provide an error such as
example source: https://jontorrado.medium.com/working-with-webpack-4-es6-postcss-with-pr...
So: Yes! we can!! - but, should we?
Comment #16
paddy_deburca commentedAnd finally, my last comment before my next one.
Using the following configuration syntax in
vitewe may be able to automatically target all subfolder of thecomponents/folder.This would try to process all
.pcss.cssfiles found in a components folder into one components CSS file. This concept may or may not work.Further reading: https://rollupjs.org/configuration-options/#input and https://vite.dev/config/build-options#build-rollupoptions
Comment #17
christian.wiedemann commentedHi @paddy_deburca,
CSS
The script is part of drupal core. (Or do I missunderstand your question.). You can find it in
web/core/scripts/css. It should run during the local or CI build process. So we maybe can reuse the script fromweb/core/scripts/cssor place a script in our scripts/css folder and execute it via package.json.Liniting
I think we should at least provide it. Other frameworks deliver mostly more preconfigured tools. So a good starting point helps.
I would vote for stylelint and prettier config.
Vite
I also vote for a separate starter kit with VITE support. When we finished we create it in a separate branch?
Comment #18
paddy_deburca commentedStylelint
Install stylelint NPM plugin
npm install -D stylelintand then the TaildwindCSS companion linternpm install -D stylelint-config-tailwindcssUpdate
postcss.config.jsto include SrtylelintThis returns an error from Stylelint stating that there is not module the defined in
package.json. So add"type": "module",to
package.json.There is another complaint that requires renaming
postcss.config.jstopostcss.config.cjs.This in turn then complains that plugins should be configured in the correct manner
Almost there.
At this point there is a depreciation notice regarding the use of The CommonJS Node.js API. This then required renaming
postcss.config.cjstopostcss.config.mjs.Now a
npm run buildexecutes and style checks the CSS.In summary
Comment #19
paddy_deburca commentedComponents
Based on the scripts in
Drupal/web/core/scripts/css, the*.pcss.cssare compiled to*.cssin each respective component folder.For this to work in the post
stylelintconfiguration, I had to convert the JS config files to MJS - requiring slight changes torequirestatements (nowimportstatements).I also limited the scope of the search for
*.pcss.cssfiles from.tocomponents.The solution works - but I have a concern or two.
In the
*.pcss.cssfiles, will there be TailwindCSS statements such as@applyor@import? Or, will the code be 'normal' CSS that can be applied directly yo an element?Comment #20
christian.wiedemann commentedHi @paddy_deburca, thanks for all your work!
I am completly fine with styleint suggestion.
To the components. Yes inside the components there should be @apply statements. Do you use the script from drupal core? Not sure if this is a problem because actually it is just another process with a diffent source file. So it should work or?
Comment #21
paddy_deburca commentedChristian,
By copying the scripts to the theme folder and by making some compatibility updates - I have a process that works-ish.
*.pcss.css files are processed and .css files are processed and created in the same folder.
But adding stylelint to this process - the process either does nothing new or nothing at all - I may be doing something wrong (but I do not see where).
To process '@apply' statements, it is necessary that TailwindCSS is loaded to understand the tag and know the utility classes - and this then includes tailwind css in all components - not just the expansion of the '@apply' statements.
To have just the minimum CSS per component, it would be necessary to load both the component CSS and the tailwind CSS, and walk through the nodes, checking component nodes against tailwind nodes, and deleting from the component CSS if they match.
This should not be impossible, but it add additional complexity and will impact the build process for component CSS.
If someone knows of an efficient way to resolve this, I would be please to know and investigate further.
Comment #22
christian.wiedemann commentedHi @paddy_deburca can you push your current theme?
Comment #23
paddy_deburca commentedHej Christian,
I have added my updated
- npm run build - will use previous method using postcss to compile the CSS - with the addition of Stylelint
- npm run build:css - will use scripts based on Drupal core to iterate through the components folder and compile *.pcss.css to *.css
The final part is not producing the desired output - comments are not being removed and stylelint is not running (I think) - no errors are produced.
I have worked with the compile.mjs file (previously compile.js) to make the process work - but I must be missing something.
I have also added a .gitignore file to avoid pushing superfluous files.
Comment #24
christian.wiedemann commentedHi @paddy_deburca,
Thanks for all your work! I checked the PostCSS pipeline and I think it is probably not the right direction.
We need to load the tailwind and its config in each post.css file and shrink out the not necessary part. It works for me more or less with this code (I did not load configs but it should):
But we need to add include statements in each file. Webpack or Vite are working differnt. They merge the CSS files together and than split them into output files in a different step. So I think when we want to provide a CLI or PostCSS Variant we should stay with the one file solution and put everything into src/css directory and no CSS files in the component folder. I will try your posted Vite configuration example .
Comment #25
christian.wiedemann commentedand sorry for point to this postcss script.
Comment #26
paddy_deburca commentedHej Cristian,
With Vite, I have only succeeded in sourcing multiple files - but the output all goes into the same file - using the Object.fromEntries(globSync()) method. The advantage is that it automatically finds all *.pcss.css files; but the disadvantage is that only one *.css file is currently being created.
Taking a step back..
During the build process
- create
_tw.csswith the current version of TailwindCSS- this file contains all the CSS statements, followed by @property statements
- split the
_tw.cssin two sections, CSS statements and @properties to give number of lines of CSS and number of lines of @properties- process all the components to create
.cssfiles- remove the CSS statements from the beginning of components
.cssfiles- remove the @propertiesfrom the end of components
.cssfiles- the remaining CSS statements should be related to the specific component
So some (pseudo) code such as
If we compress the code - we need to calculate in bytes rather than lines.
The (only) advantage with this approach is that we could use the same approach to process the theme CSS as the component CSS (tailwindcss CLI, PostCSS, ...)
Comment #27
christian.wiedemann commentedHi, I realized that you have to use @reference if you want to use multiple files without duplication of code.
With this postcss and vite and webpack works as expected. It works also for me with multiple files.
The same works also with WEBPACK with one CSS file for each entry. But either webpack as VITE actually need a dist folder. And actually a dist folder is a very nice thing.
Comment #28
paddy_deburca commentedChristian,
I have developed a JS script
- loops through all the component
.pcss.cssstylesheets- runs them through PostCSS and Tailwind
- removes the superfluous Tailwind CSS and properties from the component CSS file
produces in the component
.cssfileI still have some finessing to complete - and add stylelint and cssnano.
Comment #29
christian.wiedemann commentedYou don't need to remove the superfluous Tailwind CSS classes if you use @reference instead of "@import "tailwindcss";
Comment #30
paddy_deburca commentedChristian,
Yes - this is excellent. The use of @reference really simplifies and future proofs process.
It may be necessary to embed the Vite PostCSS/TailwindCSS process within a loop over the components folders, such that the css is generated for a single component - we can then decide if the resultant css should be under dist/ or within the actual component folder itself.
From my few tests, where I am trying to
@apply round-smto an element fails - as the utilityround-smis not defined in the app.css file. I will continue looking into this so that I can understand the process better.Comment #31
christian.wiedemann commentedThis took me also some time:) it is
@apply rounded-sm;Comment #32
christian.wiedemann commentedI was also thinking about to add the build variants as a subfolder to the theme. In each we add a package json. And maybe we share common stuff in .build folder. (not sure - I tend to overengineer stuff so what do you think?)
.build
- postcss
- vite
- webpack
Comment #33
paddy_deburca commentedChristian,
I have
Where
output.cssis the build of CSS for the theme - should contain TailwindCSS and DaisyUI.When I search
output.cssforroundedusinggrep rounded dist/css/output.css, I getWhen I try to build a component CSS using
npx tailwindcss -i components/button/button.pcss.css, I getError: Cannot apply unknown utility class: rounded-smThe input CSS file for the theme contains
@layer theme, base, components, utilities;.Is there something I am still missing from my setup with relation to using
@reference?Comment #34
g4mbinirounded-sm is not present in UI Suite DaisyUI theme. For now I only find :
rounded-md & rounded-sm (which at the end comes from Tailwind) are not at all for now in the UI Suite DaisyUI theme (maybe we can add it as utility in ui_styles.yml file if it is usefull).
Also, small alert :
select2-xxx classes don't come from Tailwind but Bootstrap. There's no select2-xxx class in DiasyUI. Although, in Bootstrap 4 you could find rounded-xxx classes.
Hope this could help ...
Comment #35
g4mbiniComment #36
paddy_deburca commented@g4mbini,
As I am only doing tests, I took inspiration from what has been done with UI Bootstrap, and am trying to make things work.
You are correct that
rounded-smdoes not exist inoutput.cssin our current configuration - however, updating thebutton.twigto make reference torounded-sm- results inrounded-smbeing included in theoutput.cssfile.My challenge is, that when I want to expend a class (in this case a class name I borrowed from Bootstrap) with
@apply rounded-sm, I get an error message.I may be missing utility class definitions (even though
@layerstatement is in theinput.cssfile).Comment #37
paddy_deburca commentedI figured it out ;-)
Rather than using
@reference "../../dist/css/output.css", I must use@reference "tailwindcss".The source CSS is
The generated CSS is
Comment #38
christian.wiedemann commentedHi @paddy_deburca,
I checked that right now and you are right. The problem behind this that our theme in css/themes/themes.css disables the default theme with
--*: initial;should be removed than everything works as expected with@reference '../../css/input.pcss.css';(Sorry propably I commited that)
Comment #39
christian.wiedemann commentedHi Paddy,
I have some open source time today. So if you push your scripts we may finalize them today so that we have a working postcss script with linting.
Comment #40
paddy_deburca commentedChristian,
I will need to make some minor adjustments to my script - I will try to merge something later this morning.
That being said, it would still be interesting to explore Vite as a possibility - and to see if we can produce one CSS file per component. Using rollup we can combine multiple input CSS into one output CSS. Question is, can we loop through the component folders, and do this for each folder.
In reality, this is what I am doing with my script, looping through the components folder, and using PostCSS to process the CSS.
Paddy.
Comment #41
paddy_deburca commentedChristian,
I have added a
process-tailwind.cjs(can be renamed) that- finds all
*.pcss.cssfiles undercomponents/folder- process each file using PostCSS and TailwindCSS
- stores the process file in the same location as original - but with a
.cssextensionIt is assumed that each
*.pcss.cssfile contains@reference 'tailwindcss';(or similar that allows discovery of TailwindCSS utilities)Possible improvements would be to improve file management in PostCSS or replace PostCSS by Vite, such that all
*.pcss.csswithin a component folder would be compiled into one.cssfile in that component folder.Comment #42
christian.wiedemann commentedHi Paddy,
thanks! I will have a look.
Comment #43
paddy_deburca commentedChristian,
I have added a Vite config file to the repo that also compiles the
*.pcss.cssto*.css.Again, possible improvement would be to combine all
*.pcss.cssfor one component into one*.cssfor that component.This may require running such a script once for each component, such as
find components -type d -depth 1 -exec npx vite build --dir "{}" \;, or something similar in JS (more portable).If this is the way we would like to go, I can update the Vite config to capture the
--dirparameter, and build one CSS per folder.Paddy.
Comment #44
paddy_deburca commentedChristian,
I have managed to be able to create a dynamic map of
componentswith*.pcss.cssfile usingWith this mapping, I can pass it to the build/rollupOptions
When run as
npx vite buildwe get❯ npx vite build
I am quiet happy with this version of the Vite configuration as it _uses_ Vite, and does not work around Vite.
Comment #45
christian.wiedemann commentedHi,
I pushed a repo with an updated postcss script and basic VITE script I did during this afternoon which is actually tries to do the same as yours. It is not working now so probably we should go with your implementation. I used workspaces to manage two build types. Postscript and VITE. Postscript works fine now with (with linting and prettier). With VITE we probably need a custom copy command to copy the generated CSS files to component folder after they are build.
Comment #46
christian.wiedemann commentedYou can do
npm run watch:css -w .build/postcssto run code in a workspace.Comment #47
paddy_deburca commentedChristian,
Setting the
dirto'.'in the configwe get the output into the components folder.
I am checking to see what may need to be configured to have
npx vite devrecompile on change to component*.pcss.cssfiles.Comment #48
paddy_deburca commentedWell, as simple as
npx vite build --watchComment #49
paddy_deburca commentedChristian,
I have updated the Vite config to also include the theme CSS (/src/css/input.css).
Vite is using PostCSS to process the CSS with TailwindCSS, stylelint, and cssnano.
Is there anything else that needs to be considered?
Should we write some Vite tests? I have never done so before, but at the moment I cannot think of anything else. :-)
Paddy.
Comment #50
christian.wiedemann commentedHi Paddy,
your VITE config is very cool! The only thing is that --emptyOutDir will propably delete the whole project. So I think the we need a dist folder and only copy the CSS files back to the src folder. According to chatgpt there are two possibilities.:
Copy after
Change dest folder
I think I would go with the copy because then it is simple to go with a dist only variant.
But I think we are nearly ready! Very cool. So the next steps from my point of view.
1. Finalize VITE config.
2. I would move the VITE config to a workspace folder under .build. (As in ui_suite_daisyui-3508143-starterkit-postcss ).
Or should we go with the VITE only? What is your opinion?
3. In the root package.json we can define a default build method which calls the watch:css and build:css in the related folder.
4. Add the example components
5. Cleanup
6. Add docs.
If you like I can do 2. and 3. @g4mbini can you help us with 4.?
Comment #51
christian.wiedemann commentedWhat I like on the workspace variant that we can easily integrate webpack (or something else in the future) and other tools like svg integration etc. without bloating the main project.
Comment #52
paddy_deburca commentedChristian,
I have updated the Vite config - the
outDiris nowdest/csswhich gets overridden on each build, so it is OK to empty it.I have updated the
packages.jsonwith a list of scripts that can be runI have 'played' with using the
--modeto set production or development mode, but as PostCSS needs to know which mode we are using in order to compress CSS or not, I had to remain with the NODE_ENV environment variable.Building the CSS is as follows:
I can move the scripts to a
.buildfolder and update the configuration to continue to deploy the CSS into the current folders. We will have three config files - Vite, PostCSS, and Stylelint.I will document the config files, and update the README.md file.
When you mention a workspace folder - what do you mean exactly? My Vite config, and other configs, currently live in the root folder of the theme. The path looks the way it does due to one too many git clones.
Comment #54
christian.wiedemann commentedHi Paddy,
Can you push your changes. I will take your changes and merge the workspace stuff into one sum-up branch to show what I mean. Than maybe we a short meeting next week to dicuss it.
Comment #56
christian.wiedemann commentedHi Paddy,
the VITE setup works very well so let's use it and forget the multi build variants. I reviewed your config and I think there two problems with it.
We should set the root folder to the root folder of the project. This is important for other plugins to ensure the right path.
root: "dist/css",. And if I change the root folder --emptyOutDir deletes the whole project. So I updated the VITE config to:I also generalized the pcss.css logic also to CSS folder and delete the src folder. This makes the glob logic easier. (src is used by drupal.)
I copied your stuff to a clean 5.0.x branch and pushed it to cleanup branch. (I think your branch was intial branched from 4.0 or?)
I also added .prettier and a .styleignore. From my point of view only the example components are missing now.
Thanks!
Comment #57
christian.wiedemann commentedI updated the CSS file structure and updated the documenation.
Comment #59
g4mbini