生成基于每个组件的Tailwind CSS输出。

huangapple go评论78阅读模式
英文:

Generating Tailwind CSS output on a per-component basis

问题

我在Blazor项目中使用Tailwind。给出的构建说明在我的网站和组件都位于同一个项目中时效果很好,因为它会捕获所有与文件通配符匹配的文件,并生成一个单独的CSS输出,其中包含多余的内容。

然而,为了更容易实现可重用性,我想将我的一些组件打包到一个单独的Razor类库中,并在每个组件上使用CSS隔离,以便仅在每个组件的基础上应用它们使用的类。这意味着为了引用它们的CSS,我只需要包含NuGet包,然后就能够提供CSS隔离,而无需进一步配置。

但是,这意味着我需要根据文件逐个生成这些文件,而不是生成一个全站范围的CSS文件。换句话说,对于每个匹配 "**/*.razor" 的文件,执行Tailwind构建过程,生成一个仅针对该文件的CSS文件,并将其写入与文件相同的位置的 .razor.css 文件中。

我发现了一个类似的问题这里,该问题建议尝试做同样的事情,但答案仅适用于生成一个单独的、项目范围的文件。再次强调,我想要为每个组件生成单独的CSS文件。

是否有人有任何关于如何实现这一目标的建议?谢谢!

英文:

I'm using Tailwind in a Blazor project. The build instructions as given work great if my website and component all live in the same project because it scoops up all the files matching the file globs and produces a single CSS output with the excess purged out.

However, in the name of easier reusability, I'd like to package up several of my components into a separate Razor class library and instead make use of CSS isolation on each of these components so that only the classes they use are applied on a per-component basis. It also means that in order to reference their CSS, I need only include the NuGet package and voila, CSS isolation is provided without any further configuration.

However, this means that instead of generating one site-wide CSS file, I instead need to generate these files on a file-by-file basis. In other words, for each file matching "**/*.razor", execute the Tailwind build process against it producing a CSS file specific to that file alone and write it to <fileName>.razor.css alongside the file.

I found a similar question here that suggests trying to do the same thing, but the answer speaks only to producing a single isolated and project-wide file. Again, I'd like to produce a separate CSS file on a per-component basis.

Does anyone have any suggestions on how I might achieve this? Thank you!

答案1

得分: 0

以下是翻译好的部分:

这当然可能有更好的方法,但至少在此期间我已经有了一个解决方案。

此解决方案要求在项目根目录中存在一个现有的 "tailwind.config.js" 文件,它将从中复制配置。配置中的 "content" 属性必须匹配一个空列表(例如 content: []),因为它将在构建过程中被替换。我的配置类似于以下内容:

const colors = require('tailwindcss/colors');

module.exports = {
    safelist: [],
    theme: {
        extend: {},
    },
    variants: {
        extend: {
            opacity: ['disabled']
        }
    },
    plugins: [
        require('@tailwindcss/forms'),
        require('@tailwindcss/aspect-ratio'),
        require('@tailwindcss/typography')
    ],
}

请注意,内容值(之前在 module.exports 中为 "content: []")已被移除。如果保留在原位,CLI 将优先考虑配置值而不是 CLI 参数,因此这里将其移除。

另外,应该存在一个包含标准 Tailwind 导入的 CSS 文件(我的文件位于 './Style/site.css')如下:

@tailwind base;
@tailwind components;
@tailwind utilities;

我已将以下 PowerShell 脚本保存到根项目目录中,命名为 "tailwindBuild.ps1"。现在,在我的项目中,唯一不想包含的 .razor 文件是 "_Imports.razor",因此它保存在 $excludedFiles 集合中 - 如果要排除其他文件,可以在那里添加更多文件。

$baseTailwindConfigPath = "./tailwind.config.js"
$baseTailwindStyleCss = "./Style/site.css"

# 获取项目目录中所有 .razor 文件的路径列表

$excludedFiles = @("_Imports.razor")
$files = Get-ChildItem -Path $dir -Recurse -File -Exclude $excludedFiles -Filter "*.razor" | Select-Object FullName

# 为每个组件生成 Tailwind 配置
foreach ($file in $files) {
    Write-Output $file

    $dirName = Split-Path $file.FullName -Parent
    $fileName = Split-Path $file.FullName -leaf
    $outputCssFileName = $dirName + "\" + $fileName + ".css"
    $tailwindConfigName = "tailwind-config-" + $fileName + ".js"
    $tailwindConfigPath = $dirName + "\" + $tailwindConfigName

    # 更新 "content: []" 
    $slashFilenameUpdate = $file.FullName.replace("\", "/")

    # 执行 Tailwind CLI 构建 CSS 文件
    tailwindcss -c $baseTailwindConfigPath -i $baseTailwindStyleCss -o $outputCssFileName --content $slashFilenameUpdate
}

最后,我们需要在 .csproj 文件中添加一些构建事件,如下所示。我将它们放在文件底部,因为我相当确定顺序不重要。

<Target Name="NodeCheck" BeforeTargets="Compile">
    <Exec Command="node --version" ContinueOnError="true">
        <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
    </Exec>
    <Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build this project" />
    <Message Importance="high" Text="Restoring dependencies via 'npm'. This may take a few minutes." />
    <Exec Command="npm install" />
    <Exec Command="npm i -g tailwindcss" />
</Target>

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="powershell.exe -ExecutionPolicy Bypass -File &quot;$(ProjectDir)tailwindBuild.ps1&quot;" />
</Target>

请注意,如果你没有将其命名为 "tailwindBuild.ps1" 或将其存储在其他位置,你应该在最后更改 ps1 文件的名称。

现在,当构建项目时,它将为每个未排除的 .razor 文件创建一个特定的 Tailwind 配置,并构建与 CSS 隔离所需匹配的最小化 Tailwind CSS 文件,然后删除所有这些剩余的 Tailwind 配置文件。

还要注意,你可能还希望更新 .gitignore 以排除 "*.razor.css",以免检入额外生成的代码。

英文:

There may certainly be a better way to do this, but I've at least got a solution in place in the meantime.

This solution requires that there be an existing 'tailwind.config.js' file in the project root from which it will copy the configuration. The 'content' property in the configuration must match an empty list (e.g. content: [],) as it will be replaced as part of the build process. Mine is similar to the following:

const colors = require(&#39;tailwindcss/colors&#39;);

module.exports = {
    safelist: [],
    theme: {
        extend: {},
    },
    variants: {
        extend: {
            opacity: [&#39;disabled&#39;]
        }
    },
    plugins: [
        require(&#39;@tailwindcss/forms&#39;),
        require(&#39;@tailwindcss/aspect-ratio&#39;),
        require(&#39;@tailwindcss/typography&#39;)
    ],
}

Note that the content value (previously "content: []" in module.exports) has been removed. If left in place, the CLI will favor the configuration value over the CLI argument, so it's removed here.

Additionally, a CSS file should exist somewhere that contains the standard Tailwind imports (mine is at './Style/site.css') as follows:

@tailwind base;
@tailwind components;
@tailwind utilities;

I've saved the following PowerShell script to my root project directory called "tailwindBuild.ps1". Now, in my project, the only .razor file I don't want included in this is "_Imports.razor", so it's saved to the $excludedFiles collection - add more there if you want to exclude other files.

$baseTailwindConfigPath = &quot;./tailwind.config.js&quot;
$baseTailwindStyleCss = &quot;./Style/site.css&quot;

# Pull a list of paths of all .razor files in project directory

$excludedFiles = @(&quot;_Imports.razor&quot;)
$files = Get-ChildItem -Path $dir -Recurse -File -Exclude $excludedFiles -Filter &quot;*.razor&quot; | Select-Object FullName

# Generate per-component tailwind config
foreach ($file in $files) {
	Write-Output $file

	$dirName = Split-Path $file.FullName -Parent
	$fileName = Split-Path $file.FullName -leaf
	$outputCssFileName = $dirName + &quot;\&quot; + $fileName + &quot;.css&quot;
	$tailwindConfigName = &quot;tailwind-config-&quot; + $fileName + &quot;.js&quot;
	$tailwindConfigPath = $dirName + &quot;\&quot; + $tailwindConfigName
			
	# Update the &quot;content: []&quot; line
	$slashFilenameUpdate = $file.FullName.replace(&quot;\&quot;, &quot;/&quot;)
	
	# Execute the Tailwind CLI to build the CSS file
	tailwindcss -c $baseTailwindConfigPath -i $baseTailwindStyleCss -o $outputCssFileName --content $slashFilenameUpdate
}

Finally, we need to add a couple of build events in our .csproj file as follows. I just put them at the bottom of the file as I'm pretty sure order doesn't matter.

	&lt;Target Name=&quot;NodeCheck&quot; BeforeTargets=&quot;Compile&quot;&gt;
		&lt;Exec Command=&quot;node --version&quot; ContinueOnError=&quot;true&quot;&gt;
			&lt;Output TaskParameter=&quot;ExitCode&quot; PropertyName=&quot;ErrorCode&quot; /&gt;
		&lt;/Exec&gt;
		&lt;Error Condition=&quot;&#39;$(ErrorCode)&#39; != &#39;0&#39;&quot; Text=&quot;Node.js is required to build this projeect&quot; /&gt;
		&lt;Message Importance=&quot;high&quot; Text=&quot;Restoring dependencies via &#39;npm&#39;. This may take a few minutes.&quot; /&gt;
		&lt;Exec Command=&quot;npm install&quot; /&gt;
		&lt;Exec Command=&quot;npm i -g tailwindcss&quot; /&gt;
	&lt;/Target&gt;

	&lt;Target Name=&quot;PostBuild&quot; AfterTargets=&quot;PostBuildEvent&quot;&gt;
	  &lt;Exec Command=&quot;powershell.exe -ExecutionPolicy Bypass -File &amp;quot;$(ProjectDir)tailwindBuild.ps1&amp;quot;&quot; /&gt;
	&lt;/Target&gt;

Note that you should change the name of the ps1 file there at the end if you're not calling it 'tailwindBuild.ps1' or if you're storing it somewhere else.

Now, when you build your project, it'll create a tailwind configuration specific to each .razor file not excluded and build the minified Tailwind CSS file under a name matching that necessary for CSS isolation, then delete all these leftover Tailwind configuration files.

Note that you might also want to update your .gitignore to exclude "*.razor.css" so you don't check in additional generated code.

huangapple
  • 本文由 发表于 2023年8月4日 03:56:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76831269.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定