在Ionic5和Angular10中使用TailwindCSS
kelvin 发布于 2021-06-04

原文:https://blog.andrewbrey.com/2020-07-06-using-tailwindcss-with-ionic-5-and-angular-10/

最近为了一些客户端工作,我不得不重新挖掘一个Ionic框架移动应用程序代码库,我最近一年多前编辑过这个代码库。在我上次参与该项目后的那段时间里,我看到了utility/functional/atomic CSS的曙光,这在很大程度上要感谢TailwindCSS的创建者Adam Wathan,他在2017年的博客中谈到了他从所谓的语义CSS到拥抱实用的演变。
另一个关于实用CSS优点的讨论(以及为什么你应该使用它)可以在johnpolacek关于重新思考CSS的精彩演讲中找到。
Simon Vrachliotis在几年前的一篇精彩演讲中称之为“实用优先”CSS的真实世界之旅,它也很好地展示了从语义CSS到实用CSS的逻辑过程。
当我在工作的时候,我发现自己一次又一次的渴望,希望预先构建的Ionic组件的人体工程学设计能像顺风工作一样令人愉快,然后灵感就来了!为什么不把顺风添加到项目中呢??。我不知道为什么我会这样粗鲁的评论,让我想到简单的增加顺风,使造型体验更好,但嘿,无论它需要什么权利?

将TailwindCSS添加到普通的Angular CLI项目

在讨论如何添加Tailwind来增强Ionic组件的预构建样式之前,我将首先介绍如何成功地将它添加到一个普通的ol’Angular项目中,而不必从Angular CLI的控制中弹出webpack配置。
由于Angular没有在webpack中使用postss加载器,因此我们不能在postss.config.js中添加另一个要求来包含Tailwind。但是,我们可以做的只是在角度网页包构建开始之前,使用从npm脚本(或选择的工具)执行的Tailwind节点二进制文件提前编译Tailwind指令,这样预构建的样式表就可以像常规CSS一样包含在网页包构建中。
如果您使用的是sass/scss,这就更容易了,因为您可以利用scss编译器中的@import语法将tailwind.css(或您命名的任何文件)包含在最终包中。如果您不使用scss,您仍然可以通过在Angular.json构建器中为包含的样式定义文件,使Angular知道该文件。
这工作得很好,但并不像我们希望的那样方便-特别是我们可能希望源文件上的文件观察器包含tailwind.config.js,以便对tailwind config的更改触发对我们的tailwind样式的重建,并随后重新生成Angular知道的样式。创建这种类型的行为并不总是直截了当的,但谢天谢地,有一个非常好的小节点模块(不是一直都有吗?)叫做ng-tailwindcss,它不仅提供了我上面描述的设置,但是也为你设置了文件观察者,每当你改变你的顺风配置时,他们会重建你的顺风风格,并把整个事情绑在一个漂亮的小蝴蝶结上!
我不会详细介绍如何设置ng-tailwindcss,因为有用的自述文件已经很好地介绍了它—需要指出的一点是,不需要从这个包中使用集成的PurgeCSS,因为Tailwind现在包含了一个开箱即用的第一类PurgeCSS集成。

将TailwindCSS添加到使用Angular的Ionic5项目

好吧,对于一个香草Angular项目来说,很多情况仍然适用于Ionic+Angular,这可能不太令人惊讶,因为自从Ionic4以来,框架转向Web组件,并与Angular分离。在这样做的过程中,他们很大程度上脱离了项目结构的业务,并遵从所选择的框架来做出这些选择。
也就是说,这是默认的Ionic5与global.scss看起来像一个项目与空白起动器脚手架:

/*
 * App Global CSS
 * ----------------------------------------------------------------------------
 * Put style rules here that you want to apply globally. These styles are for
 * the entire app and not just one component. Additionally, this file can be
 * used as an entry point to import other CSS/Sass files to be included in the
 * output CSS.
 * For more information on global stylesheets, visit the documentation:
 * https://ionicframework.com/docs/layout/global-stylesheets
 */

/* Core CSS required for Ionic components to work properly */
@import '~@ionic/angular/css/core.css';

/* Basic CSS for apps built with Ionic */
@import '~@ionic/angular/css/normalize.css';
@import '~@ionic/angular/css/structure.css';
@import '~@ionic/angular/css/typography.css';
@import '~@ionic/angular/css/display.css';


/* Optional CSS utils that can be commented out */
@import '~@ionic/angular/css/padding.css';
@import '~@ionic/angular/css/float-elements.css';
@import '~@ionic/angular/css/text-alignment.css';
@import '~@ionic/angular/css/text-transformation.css';
@import '~@ionic/angular/css/flex-utils.css';

您会注意到框架中已经包含了一些实用程序样式表-我不想要这些样式表,因为我将要使用Tailwind,而且我还需要确保包含Tailwind版本的normalize,因为它做了重置通常不会做的一两件事,也就是说,添加默认边框颜色gray-500,否则通常默认边框颜色为transparent。
如果您很好奇,那么您可以简单地将border添加到元素中,而不必执行border-gray-500使默认边框可见。
我还需要确保我不会因为Ionic风格而损失太多,因为他们的Web组件有很多我依赖的风格方面。我需要的是,在我正常的角度只增加了顺风是能够模拟分裂我的顺风指令分开的方式建议的顺风文件,以便我可以确保预期的特殊性适用于我的顺风类相比,那些来自Ionic。
我决定通过将每个指令(即@base、@utilities和@components)的编译拆分为一个单独的预构建步骤来实现这一点,从而将它们导入到我的global.scss中,与我保留的离子导入相比,它们处于正确的相对位置。比如:

/*
 * App Global CSS
 * ----------------------------------------------------------------------------
 * Put style rules here that you want to apply globally. These styles are for
 * the entire app and not just one component. Additionally, this file can be
 * used as an entry point to import other CSS/Sass files to be included in the
 * output CSS.
 * For more information on global stylesheets, visit the documentation:
 * https://ionicframework.com/docs/layout/global-stylesheets
 */

/* Core CSS required for Ionic components to work properly */
@import '~@ionic/angular/css/core.css';

/* 
 Use the Tailwind reset instead of the one 
 from Ionic because it sets some required 
 defaults for Tailwind
*/
@import './styles/tailwind/base.css';

/* Basic CSS for apps built with Ionic */
@import '~@ionic/angular/css/structure.css';
@import '~@ionic/angular/css/typography.css';
@import '~@ionic/angular/css/display.css';

@import './styles/tailwind/components.css';

/* Optional CSS utils that can be commented out */
// @import '~@ionic/angular/css/padding.css';
// @import '~@ionic/angular/css/float-elements.css';
// @import '~@ionic/angular/css/text-alignment.css';
// @import '~@ionic/angular/css/text-transformation.css';
// @import '~@ionic/angular/css/flex-utils.css';

@import './styles/tailwind/utilities.css';

// Other normal imports...
@import './styles/abstracts/fonts';

请注意,现在我不使用Ionic utility,我使用所有的Tailwind!

ng-tailwindcss的配置

尽管没有严格的必要,我还是决定继续使用ng-tailwindcss,因为它在tailwindcli之上提供了一个很好的抽象。我创建了以下package.json脚本来分别调用它3次,每次一次用于Tailwind指令:

"scripts": {
  "tailwind": "yarn tw:base && yarn tw:utilities && yarn tw:components",
  "tailwind:prod": "PURGE_TW=true yarn tailwind",
  "tw:base": "ngtw b -c ng-tailwind/ng-tailwind.base.js",
  "tw:utilities": "ngtw b -c ng-tailwind/ng-tailwind.utilities.js",
  "tw:components": "ngtw b -c ng-tailwind/ng-tailwind.components.js"
}

出于不希望package.json中的行太长的原因,我将脚本拆分为一个小名称空间tw:,然后生成一对“父”脚本,用于构建用于开发和生产的所有内容(其中清除将由Tailwind cli调用)。
您将注意到,3 tw: namespace 脚本中对ngtw的每个调用都包含一个-c标志,该标志指向一个ng tailwindcss配置文件。每个文件看起来都像

// For example, the compilation of @base looks like this

module.exports = {
    configJS: './tailwind.config.js',
    sourceCSS: './src/styles/ng-tailwind/base.css',
    outputCSS: './src/styles/tailwind/base.css',
    sass: false,
    purge: false,
};

反过来,您将看到ngtw的每个配置文件都指向一个要编译的css文件和一个要输出的css文件。我在git中包含了sourceCSS文件,因为它看起来就像

// ./src/styles/ng-tailwind/base.css
@tailwind base;

然后我就忽略了编译过的文件,例如../src/styles/tailwind/base.css,但是正是这些编译过的文件包含在上面的global.scss中。这使我能够像postss编译一样将Tailwind css文件拆分,并且确保我的repo-woo中不包含大量的Tailwind开发css文件!

添加到Ionic dev服务器和生产构建中

由于这些基本上都只是预编译css,因此添加到构建(开发和生产)实际上只是在调用其他构建命令之前调用脚本的问题—以下是my package.json中的完整脚本键:

"scripts": {
  "start": "yarn tailwind && ionic serve --no-open --lab --external -- --proxy-config proxy.conf.json",
  "tailwind": "yarn tw:base && yarn tw:utilities && yarn tw:components",
  "tailwind:prod": "PURGE_TW=true yarn tailwind",
  "emulate": "yarn clean && yarn tailwind && env-cmd --use-shell \"ionic cordova emulate ios --buildConfig build.json -- -- --storePassword=$KEYSTORE_PASSWORD --password=$KEY_PASSWORD\"",
  "build": "yarn clean && yarn tailwind:prod && env-cmd --use-shell \"ionic cordova build ios --prod --release --device --buildConfig build.json -- -- --storePassword=$KEYSTORE_PASSWORD --password=$KEY_PASSWORD\"",
  "tw:base": "ngtw b -c ng-tailwind/ng-tailwind.base.js",
  "tw:utilities": "ngtw b -c ng-tailwind/ng-tailwind.utilities.js",
  "tw:components": "ngtw b -c ng-tailwind/ng-tailwind.components.js"
}

统一Tailwind和Ionic

另一个需要考虑的问题是,你不想随风践踏所有的爱奥尼亚风格(最有可能)。您可以通过tailwind.config.js中的一些仔细考虑来帮助实现这一点。这是我在这个项目中使用的一个:

module.exports = {
    purge: {
        enabled: process.env.PURGE_TW === 'true',
        content: ['./src/**/*.html', './src/**/*.ts'],
    },
    theme: {
        extend: {},
        colors: {
            primary: {
                default: 'var(--ion-color-primary)',
                shade: 'var(--ion-color-primary-shade)',
                tint: 'var(--ion-color-primary-tint)',
            },
            secondary: {
                default: 'var(--ion-color-secondary)',
                shade: 'var(--ion-color-secondary-shade)',
                tint: 'var(--ion-color-secondary-tint)',
            },
            tertiary: {
                default: 'var(--ion-color-tertiary)',
                shade: 'var(--ion-color-tertiary-shade)',
                tint: 'var(--ion-color-tertiary-tint)',
            },
            light: {
                default: 'var(--ion-color-light)',
                shade: 'var(--ion-color-light-shade)',
                tint: 'var(--ion-color-light-tint)',
            },
            medium: {
                default: 'var(--ion-color-medium)',
                shade: 'var(--ion-color-medium-shade)',
                tint: 'var(--ion-color-medium-tint)',
            },
            dark: {
                default: 'var(--ion-color-dark)',
                shade: 'var(--ion-color-dark-shade)',
                tint: 'var(--ion-color-dark-tint)',
            },
            success: {
                default: 'var(--ion-color-success)',
                shade: 'var(--ion-color-success-shade)',
                tint: 'var(--ion-color-success-tint)',
            },
            warning: {
                default: 'var(--ion-color-warning)',
                shade: 'var(--ion-color-warning-shade)',
                tint: 'var(--ion-color-warning-tint)',
            },
            danger: {
                default: 'var(--ion-color-danger)',
                shade: 'var(--ion-color-danger-shade)',
                tint: 'var(--ion-color-danger-tint)',
            },
            step: {
                '50': 'var(--ion-color-step-50)',
                '100': 'var(--ion-color-step-100)',
                '150': 'var(--ion-color-step-150)',
                '200': 'var(--ion-color-step-200)',
                '250': 'var(--ion-color-step-250)',
                '300': 'var(--ion-color-step-300)',
                '350': 'var(--ion-color-step-350)',
                '400': 'var(--ion-color-step-400)',
                '450': 'var(--ion-color-step-450)',
                '500': 'var(--ion-color-step-500)',
                '550': 'var(--ion-color-step-550)',
                '600': 'var(--ion-color-step-600)',
                '650': 'var(--ion-color-step-650)',
                '700': 'var(--ion-color-step-700)',
                '750': 'var(--ion-color-step-750)',
                '800': 'var(--ion-color-step-800)',
                '850': 'var(--ion-color-step-850)',
                '900': 'var(--ion-color-step-900)',
                '950': 'var(--ion-color-step-950)',
            },
        },
    },
    variants: {},
    corePlugins: {
        textOpacity: false,
        backgroundOpacity: false,
    },
    plugins: [],
};

你会注意到一些事情,比如

我使用离子风格的自定义属性,而不是相应的hex/rgb值,而且,我这样做的同时覆盖Tailwind的colors键。当我从爱奥尼亚得到一个完整的调色板时,根本不需要编译所有的顺风颜色,我可以让爱奥尼亚的配置有一个唯一的真实来源。

我关闭了textOpacity和backgroundOpacity插件-这是一个真正的影响,没有统一的“样式是如何制作的”过程。我的颜色变量,由于你如何配置在离子样式,要么是十六进制代码是不兼容的CSS rgba函数(这是颜色不透明工具的工作方式),或部分rgb值像255,255,255(但不是rgb(255,255,255))白色。我想这会对Tailwind起作用,但是我决定我不想为我所有的颜色和变体声明这些类型的变量。在爱奥尼亚,有太多的颜色可以指定变量,我不想为了一些半透明的文本而费心。

包装

总的来说没那么糟吧?一旦你意识到顺风编译并不是什么postss魔法,那么很明显,前进的道路就是在手动编译css的生命周期中增加一点自动化。通过这种设置,我可以更改任何css并查看实时重新加载,甚至可以对tailwind.config.js进行更改,并实时重新加载更改(在开发人员中进行tailwind编译需要几秒钟),因为最终,您只需在scss构建管道中包含另一个css文件,Angular非常了解如何处理它!

我发现用少量的Tailwind来增强Ionic是非常值得努力的,更好的是我从我的包中获得了大量的Ionic css,而不是只包含一个我关心的Tailwind实用程序的purgable块-给它一个关于你的下一个Ionic Angular项目的镜头:)

kelvin
关注 私信
文章
92
关注
0
粉丝
0