如何将Tailwind CSS添加到Blazor应用程序中?

29
特别是,我正在使用ASP.NET Core Preview 8的Blazor(服务器托管)。我尝试使用LibMan添加它,但那似乎更多是关于从CDN下载文件。我想将Tailwind引入我的构建过程中。
这种情况下,我应该使用类似Webpack的工具吗?如果是这样,如何使Webpack成为我的构建过程的一部分?

随着 Blazor 的持续发展,这个问题的重要性会增加。我已经进行了编辑,并希望它能够重新打开,因为它需要更新。 - Neil Meyer
1
这似乎是一个合理的“如何”问题。 - H H
5个回答

59

2022更新

以下是原始回答...

自我提出这个问题以来,时间已经过去了。例如,现在我正在面向支持ES6的现代浏览器,而无需使用Babel(这也是我使用Webpack的主要原因)。

所以我想记录一下我的当前解决方案(通过npm安装Tailwind cli,无需Webpack)

假设您已经安装了npm(属于node.js)。在您的项目根目录中:

npm init -y

这将创建一个package.json文件。这是我的文件外观:
{
  "name": "holly",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

NB - 我将name(文件夹/项目名称为“Holly”)改为小写字母。我使用VS Code查看文件时发现有一条波浪线!

接下来,我安装Tailwind:

npm install -D tailwindcss cross-env

我还添加了cross-env - 这样我就可以在我的开发机器(Windows)和 GitHub Action 中运行相同的命令。

之后,生成 Tailwind 配置文件:

npx tailwindcss init

这应该创建一个类似于这样的文件:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [],
  theme: {
    extend: {},
  },
  plugins: [],
}

我正在使用ASP.NET Core/Blazor Server。因此,我将content属性设置为以下内容:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./**/*.{razor,cshtml,html}"],
  theme: {
    extend: {},
  },
  plugins: [],
}

现在Tailwind已经配置好了,我们需要一个输入文件来生成CSS。在我的项目中,我创建了一个名为Styles的文件夹和一个名为app.css的文件:

@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

下一步是创建一些方便的npm脚本。这是我的package.json文件现在的样子:
{
  "name": "holly",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "dependencies": {},
  "devDependencies": {
    "cross-env": "^7.0.3",
    "tailwindcss": "^3.2.4"
  },
  "scripts": {
    "build": "cross-env NODE_ENV=development ./node_modules/tailwindcss/lib/cli.js -i ./Styles/app.css -o ./wwwroot/css/app.css",
    "watch": "cross-env NODE_ENV=development ./node_modules/tailwindcss/lib/cli.js -i ./Styles/app.css -o ./wwwroot/css/app.css --watch",
    "release": "cross-env NODE_ENV=production ./node_modules/tailwindcss/lib/cli.js -i ./Styles/app.css -o ./wwwroot/css/app.css --minify"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
  • build将被Visual Studio在DEBUG模式下使用
  • watch只是在开发模式下进行即时更新的方便工具。
  • release用于生产环境。

最后,将以下内容添加到您的项目文件中(在我的情况下为Holly.csproj):

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>

    <NpmLastInstall>node_modules/.last-install</NpmLastInstall>
  </PropertyGroup>

  <!-- Items removed for brevity --> 

  <Target Name="CheckForNpm" BeforeTargets="NpmInstall">
    <Exec Command="npm -v" ContinueOnError="true">
      <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
    </Exec>
    <Error Condition="'$(ErrorCode)' != '0'" Text="You must install NPM to build this project" />
  </Target>

  <Target Name="NpmInstall" BeforeTargets="BuildCSS" Inputs="package.json" Outputs="$(NpmLastInstall)">
    <Exec Command="npm install" />
    <Touch Files="$(NpmLastInstall)" AlwaysCreate="true" />
  </Target>

  <Target Name="BuildCSS" BeforeTargets="Compile">
    <Exec Command="npm run build" Condition=" '$(Configuration)' == 'Debug' " />
    <Exec Command="npm run release" Condition=" '$(Configuration)' == 'Release' " />
  </Target>
</Project>

这是基于我找到的由Chris Sainty撰写的教程(目前无法找到)。但是,我找到了Chris关于将Tailwind CSS v3添加到Blazor应用程序的出色文章。尽管我认为此版本避免了与Visual Studio的集成。

确保将NpmLastInstall元素和Target元素复制并粘贴到您的.csproj文件的适当位置。

如果您处于DEBUG模式,则Visual Studio将执行npm run build。如果您处于RELEASE模式,则它将执行npm run release。如果您刚从服务器上拉取了存储库,则Visual Studio应聪明地自动执行npm install。唯一的问题是,我认为当更新了package.json文件时,它不会运行npm install - 您需要记得手动执行此操作。

.csproj文件中针对npm,这意味着当ASP.NET Core项目构建时,Tailwind将进行构建。事情将保持一致-如果您按F5,则知道css已经更新! Tailwind JIT默认打开-因此,Tailwind构建时间可以忽略不计,并且不会增加总构建时间太多。

最后一件事。因为Tailwind css由Visual Studio项目更新,这意味着在云中也会发生同样的事情。这是我GitHub操作的简化版本:

name: production-deployment

on:
  push:
    branches: [ master ]

env:
  AZURE_WEBAPP_NAME: holly
  AZURE_WEBAPP_PACKAGE_PATH: './Holly'
  DOTNET_VERSION: '6.0.x'
  NODE_VERSION: '12.x'

jobs:
  build-and-deploy-holly:
    runs-on: ubuntu-latest
    steps:
      # Checkout the repo
      - uses: actions/checkout@master

      # Setup .NET Core 6 SDK
      - name: Setup .NET Core ${{ env.DOTNET_VERSION }}
        uses: actions/setup-dotnet@v1
        with:
          dotnet-version: ${{ env.DOTNET_VERSION }}

      # We need Node for npm!
      - name: Setup Node.js ${{ env.NODE_VERSION }}
        uses: actions/setup-node@v1
        with:
          node-version: ${{ env.NODE_VERSION }}

      # Run dotnet build and publish for holly
      - name: Dotnet build and publish for holly
        env:
          NUGET_USERNAME: ${{ secrets.NUGET_USERNAME }}
          NUGET_PASSWORD: ${{ secrets.NUGET_PASSWORD }}
        run: |
          cd '${{ env.AZURE_WEBAPP_PACKAGE_PATH }}'
          dotnet build --configuration Release /warnaserror
          dotnet publish -c Release -o 'app'

      # Deploy holly to Azure Web apps
      - name: 'Run Azure webapp deploy action for holly using publish profile credentials'
        uses: azure/webapps-deploy@v2
        with:
          app-name: ${{ env.AZURE_WEBAPP_NAME }} # Replace with your app name
          publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE  }} # Define secret variable in repository settings as per action documentation
          package: '${{ env.AZURE_WEBAPP_PACKAGE_PATH }}/app'

在运行dotnet build命令之前,Setup Node.js步骤确保npm可用。 dotnet build命令将触发Tailwind构建过程。由于cross-env的存在,同样的命令将适用于Windows、macOS或Linux机器。

我想这就是全部内容了!

原始回答

在查看了这篇SO post中的信息后。以下是我最终实现的简要说明。它并不完美,还需要一些工作。但它是一个很好的起点(而不会使事情变得太复杂)。

创建npm包

我在解决方案的根目录下运行了npm init - 这将创建一个package.json文件。根据我读到的建议,这不应该在项目/子文件夹下创建。

安装/配置Webpack

根据webpack安装指南,我执行了以下操作:

npm install webpack webpack-cli --save-dev

为了准备我的Tailwind设置,我还安装了以下内容(有关更多详细信息,请参见下面的webpack.config.js文件):

npm install css-loader postcss-loader mini-css-extract-plugin --save-dev
npm install tailwindcss postcss-import

这是我的webpack.config.js文件。请注意,它主要用于处理Tailwind的css:

const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const bundleFileName = 'holly';
const dirName = 'Holly/wwwroot/dist';

module.exports = (env, argv) => {
    return {
        mode: argv.mode === "production" ? "production" : "development",
        entry: ['./Holly/wwwroot/js/app.js', './Holly/wwwroot/css/styles.css'],
        output: {
            filename: bundleFileName + '.js',
            path: path.resolve(__dirname, dirName)
        },
        module: {
            rules: [{
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader'
                ]
            }]
        },
        plugins: [
            new MiniCssExtractPlugin({
                filename: bundleFileName + '.css'
            })
        ]
    };
};


在 CSS 方面,这将采用一个单一的入口点 styles.css(位于名为"Holly"的子文件夹/项目下)并使用 PostCSS/Tailwind CSS 进行处理。CSS 被分成不同的文件,但由 postcss-import 处理 (稍后会详细介绍)。所有的 CSS 都被编译成一个名为 holly.css 的文件。
管理多个 CSS 文件
我还有一个 postcss.config.js 文件在解决方案的根目录中:
module.exports = {
  plugins: [
    require('postcss-import'),
    require('tailwindcss'),
    require('autoprefixer'),
  ]
}

这将为Tailwind配置PostCSS,但也包括postcss-import。在Webpack配置中,styles.css是处理的入口点:

@import "tailwindcss/base";
@import "./holly-base.css";

@import "tailwindcss/components";
@import "./holly-components.css";

@import "tailwindcss/utilities";

根据Tailwind 文档postcss-import 模块会在应用 Tailwind CSS 之前预处理 @import 语句。 使其工作 一旦所有配置都完成,我向 npm 包添加了以下脚本:
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --progress --profile",
    "watch": "webpack --progress --profile --watch",
    "production": "webpack --progress --profile --mode production"
  },

为了将Tailwind应用于styles.css文件,我运行了以下命令:

npm run build

如果能让Visual Studio在文件被更改时运行上述命令(并保证在调试应用程序时等待编译),并且让Visual Studio显示错误信息,那就太好了。但这是另一回事/更加困难。所以我选择了以下工作流程。

当我在我的计算机上进行调试时,我在打开的终端中运行此命令:

npm run watch

每当 .css 文件发生变化时,都会生成一个新的 holly.css 文件。这在应用程序运行时很好用——我只需要在进行更改后刷新页面即可。
生产服务器在 Docker 容器内运行。因此,我最终在 Dockerfile 中调用了 npm run production 命令:
# Latest .NET Core from https://hub.docker.com/_/microsoft-dotnet-core-sdk/ (not the nightly one)
FROM mcr.microsoft.com/dotnet/core/sdk:3.0.100-preview9-disco AS build-env

# Setup npm!
RUN apt-get -y update && apt-get install npm -y && apt-get clean

WORKDIR /app
COPY . ./

# To run Tailwind via Webpack/Postcss
RUN npm install
RUN npm run production

RUN dotnet restore "./Holly/Holly.csproj"
RUN dotnet publish "./Holly/Holly.csproj" -c Release -o out

正如您所看到的,构建过程并不像在Visual Studio中点击“开始”按钮那么简单。但是,工作流程对于团队中的其他成员来说足够简单易学。如果上述工作流程出现问题,我将在那时考虑我的选择。

接下来,我可能会专注于删除未使用的Tailwind CSS

如果有任何不清楚或可以改进的地方,请告诉我!


1
这个没有赞怎么可能呢?这可能是我在大约一个小时的研究中找到的最简单的答案了。 - agrath
2
在完整的 VS 中,根据 https://code.visualstudio.com/api/working-with-extensions/bundling-extension 的说明,你可以将 webpack 和 webpack-dev 脚本添加到 package.json 文件中,然后在 VS 包管理器控制台中输入 npm run webpack-dev 命令来监听 CSS 文件的变化并实现自动重构。 - agrath
我后来意识到你在演示中实际上也是用了同样的方法,只不过名字不同。唯一的区别是我是从 PMC 而不是独立的命令窗口来运行 watch。虽然这会阻止 PMC 用于安装 NuGet 包,所以你必须停止 watch 才能执行该操作。 - agrath
1
非常有帮助。即使使用了你的Tailwind配置,我仍然无法让“watch”检测到更改,但我会解决的。 - kenchilada
@kenchilada,你设置了content属性吗? - Mitkins
显示剩余3条评论

13

我最近也问了自己同样的问题。我决定不喜欢在项目中使用package.json或node_modules目录。出于这些原因,我创建了一个NuGet包并添加了新的构建操作。

使用这个构建操作,你只需给你的样式表添加"TailwindCSS"构建操作,在构建过程中,样式表将通过PostCSS进行转换。

更多详情请参阅GitHub资源库


我喜欢这个。但是有哪些先决条件呢?我假设需要安装Node和npm,还有一些其他的包吗? - Alex from Jitbit
是的,你说得对。这取决于节点和npm,所需的软件包(tailwindcss、postcss等)将由MSBuild目标安装。 - BamButz
我已经在 Blazor 项目中安装了该扩展,但是我找不到配置输入 CSS 路径的方法。 - mrapi

0

更新以反映Tailwind实验室内的更改:

创建了一个新的独立CLI,允许在不安装webpacknodejs / npm的情况下使用CLI。

下载exe(适用于macOS和linux),并像使用普通cli一样在proj目录中运行它。

详细信息请参见: https://tailwindcss.com/blog/standalone-cli


0

在提问时,这里给出的答案可能是最好的方法。随着Tailwind的发展,现在有了其他替代方法:

最近我开始使用这种方法,它更简单,不需要npm:https://github.com/tesar-tech/BlazorAndTailwind

非常容易设置,后台运行tailwind watch效果很好。


尝试了您的解决方案并在myproject.csproj中添加了Exec命令,css文件仅在项目首次运行时创建,之后不会重新构建。 - mrapi

0

安装Tailwind版本3 - 2023年更新:

CDN

将Tailwind CSS安装到Blazor应用程序中的第一种最简单的方法是使用CDN。使用TW 3,CDN提供JS库而不再仅是静态CSS文件。

要添加CDN,请将以下脚本代码添加到WASM应用程序的index.html文件的头部,对于Blazor Server App,请添加到_hosts.cshtml文件中。

<head>
...
<title>Tailwind via Play CDN</title>
<base href="/" />
<script src="https://cdn.tailwindcss.com"></script>

虽然这对于小型项目和学习来说是可以的,但使用CDN会使生产环境变得更加复杂。

单页应用程序的整个理念是减少对服务器调用的不断需求。现在你正在使用需要每次页面加载时调用服务器的CDN。这种方法对于生产环境来说并不理想。

将Tailwind安装到项目中。

有两种基本的方法可以将TW 3纳入您的blazor项目中。

  1. 使用CLI
  2. 使用现有工具(如Webpack)的Post CSS

如果您已经使用某种JS实现,则使用PostCSS最好。

当涉及到CLI时,现在有两个选项可供选择。

  1. 使用像NPM这样的包管理器
  2. 使用独立的CLI

使用NPM

如果您的应用程序已经使用了NPM或者您作为开发人员已经熟悉使用NPM,那么这将是更好的选择。

您可以使用以下命令在全局安装TW3。

npm install -g tailwindcss

然后从您的 Blazor 应用程序根目录,您可以使用以下命令将 TW3 安装到您的项目中。

npx tailwindcss init

这将创建一个名为 tailwind.config.js 的文件,其内容如下...

module.exports = {
  content: [],
  theme: {
    extend: {},
  },
  plugins: [],
}

我们需要做的就是告诉CLI它应该寻找哪些文件格式。可以通过添加以下内容来实现。
请注意,cshtml文件适用于Blazor Server应用程序,而HTML和Razor文件则足以满足WASM应用程序的需求。此代码片段包括所有三种文件类型。

module.exports = {
  content: ["./src/**/*.{razor,html,cshtml}"],
  theme: {
    extend: {},
  },
  plugins: [],
}

下一步是创建一个源CSS文件。
您可以创建一个单独的文件夹和CSS文件,然后添加以下代码行。

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

以下是 TW3 指令,它们将被替换为应用程序中 TW 类可能使用的任何 CSS。

现在我们可以使用终端启动 TW3 CLI。

npx tailwindcss -i path-to-file-we-created/file-name.css -o ./wwwroot/app.css --watch

在这种情况下,制造的 CSS 将被导出到 wwwroot 文件夹。如果您希望它出现在其他位置,请相应更改路径。

谜题的最后一块是向 Blazor 应用程序的主机页面添加对此 CSS 文件的引用,如下所示...

<head>
    ...
    <title>Tailwind via NPM</title>
    <base href="/" />
    <link href="app.css" rel="stylesheet" />
</head>

使用独立的CLI。很多步骤都是相同的。首先,您必须从TW存储库中下载独立的CLI,可以在此处找到[1]。请花点时间下载适合您操作系统的正确CLI。
然后将可执行文件添加到应用程序的根文件夹中,并以相同的方式使用它。
生成配置文件。
./tailwindcss init
使用文件扩展名更新它。

module.exports = {
  content: ["./src/**/*.{razor,html,cshtml}"],
  theme: {
    extend: {},
  },
  plugins: [],
}

创建源CSS文件并添加指令。

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

我们可以使用类似的命令来运行独立的CLI。 npx tailwindcss -i path-to-file-we-created/file-name.css -o ./wwwroot/app.css --watch 最后,我们可以在根HTML文件中添加对CSS文件的引用。

<head>
    ...
    <title>Tailwind via Standalone CLI</title>
    <base href="/" />
    <link href="app.css" rel="stylesheet" />
</head>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接