weapp-tailwindcss-webpack-plugin
把
tailwindcss带入小程序开发吧!
- weapp-tailwindcss-webpack-plugin
2.x 版本特性
2.2.0版本后,所以 v1 版本的插件被去除,如果你还是想用 v1 插件,请锁定你的版本在2.1.5
这个版本新增了 UnifiedWebpackPluginV5
和 UnifiedViteWeappTailwindcssPlugin 这种 Unified 开头的插件。
它们能够自动识别并精确处理所有 tailwindcss 的工具类。这意味着它可以同时处理所有文件中的静态或动态的 class。
相比v1版本只有处理wxss,wxml静态class的能力,使用v2版本新的插件,你再也不需要在 js 里引入并调用标记方法 replaceJs了!2.x 插件有精准转化 js/jsx 的能力,大大提升了 taro 这种动态模板框架的开发体验。
插件介绍
UnifiedWebpackPluginV5 是一个核心插件,所有使用 webpack 进行打包的框架都可以使用它,只需要传入 appType 配置项: uni-app/taro/rax/remax/mpx 等等,如果不传的话,插件会去猜测公共的样式文件位置,并进行转化(有可能不准确)。
目前,这个方案只支持 tailwindcss v3.x.x 版本和 webpack5。同时这个方案依赖 monkey patch,所以你应该把
"scripts": {
+ "postinstall": "weapp-tw patch"
}加入你的 package.json。当然在安装或者更新 tailwindcss 后,手动执行 npx weapp-tw patch 效果也是一样的,看到 patch .... successfully 表示成功。
UnifiedViteWeappTailwindcssPlugin 为 vite 专用插件,配置项和使用方式也是和上面一致的。
Usage
1. 安装配置 tailwindcss
安装 tailwindcss
1. 安装 tailwindcss
# npm / yarn / pnpm
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init2. 把 tailwindcss 注册进 postcss.config.js
// postcss.config.js
// 假如你使用的框架/工具不支持 postcss.config.js,则可以使用内联的写法
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
}
}3. 配置 tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
// 这里给出了一份 uni-app /taro 通用示例,具体要根据你自己项目的目录进行配置
// 不在 content 包括的文件内,不会生成工具类
content: ['./public/index.html', './src/**/*.{html,js,ts,jsx,tsx,vue}'],
corePlugins: {
// 不需要 preflight,因为这主要是给 h5 的,如果你要同时开发小程序和 h5 端,你应该使用环境变量来控制它
preflight: false
}
}4. 引入 tailwindcss
在你的项目入口引入 tailwindcss
比如 uni-app 的 App.vue
<style>
@tailwind base;
@tailwind utilities;
/* 使用 scss */
/* @import 'tailwindcss/base'; */
/* @import 'tailwindcss/utilities'; */
</style>又或者 Taro 的 app.scss
@import 'tailwindcss/base';
@import 'tailwindcss/utilities';然后在 app.ts 里引入
Q&A: 为什么没有引入
tailwindcss/components? 是因为里面默认存放的是 pc 端自适应相关的样式,对小程序环境来说没有用处。如果你有 @layer components 相关的工具类需要使用,可以引入。
2. rem 转 px 或 rpx
配置tailwindcss单位转化
1. 两种转化方式(二者选其一即可)
假如你想要把项目里,所有满足条件的 rem 都转化成 rpx,那么 postcss plugin: postcss-rem-to-responsive-pixel 适合你。
假如你想缩小一下范围,只把 tailwindcss 中默认的工具类的单位(非jit生成的class),从 rem 转变为 rpx,那么 tailwindcss preset: tailwindcss-rem2px-preset 适合你。
2. postcss-rem-to-responsive-pixel
npm i -D postcss-rem-to-responsive-pixel安装好之后,把它注册进你的 postcss.config.js 即可:
// postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
'postcss-rem-to-responsive-pixel': {
// 32 意味着 1rem = 32rpx
rootValue: 32,
// 默认所有属性都转化
propList: ['*'],
// 转化的单位,可以变成 px / rpx
transformUnit: 'rpx',
},
},
};3. tailwindcss-rem2px-preset
npm i -D tailwindcss-rem2px-preset然后在 tailwind.config.js 中,添加:
// tailwind.config.js
module.exports = {
presets: [
require('tailwindcss-rem2px-preset').createPreset({
// 32 意味着 1rem = 32rpx
fontSize: 32,
// 转化的单位,可以变成 px / rpx
unit: 'rpx'
})
],
// ...
}这样即可完成 tailwindcss 默认 rem 单位,转化 rpx 的配置了。
3. 安装这个插件
# npm / yarn /pnpm
npm i -D weapp-tailwindcss-webpack-plugin
# 可以执行一下 patch 方法
npx weapp-tw patch然后把下列脚本,添加进你的 package.json 的 scripts 字段里:
"scripts": {
+ "postinstall": "weapp-tw patch"
}各个框架注册的方式
uni-app (vue2/3)
在创建uni-app项目时,请选择uni-app alpha版本
vue create -p dcloudio/uni-preset-vue#alpha my-alpha-project这是因为默认创建的版本还是 @vue/cli 4.x 的版本,使用 webpack4 和 postcss7,而 alpha 版本使用 @vue/cli 5.x 即 webpack5 和 postcss8,这可以使用最新版本的 tailwindcss 和本插件。
// 在 vue.config.js 里注册
const { UnifiedWebpackPluginV5 } = require('weapp-tailwindcss-webpack-plugin')
/**
* @type {import('@vue/cli-service').ProjectOptions}
*/
const config = {
// some option...
configureWebpack: (config) => {
config.plugins.push(
new UnifiedWebpackPluginV5({
appType: 'uni-app'
})
)
}
// other option...
}
module.exports = configuni-app vite(vue3)
// vite.config.[jt]s
import { UnifiedViteWeappTailwindcssPlugin as uvwt } from 'weapp-tailwindcss-webpack-plugin/vite'
const vitePlugins = [uni(),uvwt()]
export default defineConfig({
plugins: vitePlugins,
// 假如 postcss.config.js 不起作用,请使用内联 postcss Latset
// css: {
// postcss: {
// plugins: postcssPlugins,
// },
// },
});Taro v3 (all frameworks)
在使用Taro时,检查一下把 config/index 的配置项 compiler 设置为 'webpack5'
// config/index
const { UnifiedWebpackPluginV5 } = require('weapp-tailwindcss-webpack-plugin')
{
mini: {
webpackChain(chain, webpack) {
chain.merge({
plugin: {
install: {
plugin: UnifiedWebpackPluginV5,
args: [{
appType: 'taro'
}]
}
}
})
}
}
}mpx (原生增强)
在 vue.config.js 中注册:
// vue.config.js
const { defineConfig } = require('@vue/cli-service')
const { UnifiedWebpackPluginV5 } = require('weapp-tailwindcss-webpack-plugin')
module.exports = defineConfig({
// other options
configureWebpack(config) {
config.plugins.push(new UnifiedWebpackPluginV5({
appType: 'mpx'
}))
}
})rax (react)
在根目录下创建一个 build.plugin.js 文件,然后在 build.json 中注册:
{
"plugins": [
"./build.plugin.js"
],
}回到 build.plugin.js
// build.plugin.js
const { UnifiedWebpackPluginV5 } = require('weapp-tailwindcss-webpack-plugin')
module.exports = ({ context, onGetWebpackConfig }) => {
onGetWebpackConfig((config) => {
config.plugin('UnifiedWebpackPluginV5').use(UnifiedWebpackPluginV5, [
{
appType: 'rax',
},
]);
});
};原生开发 (webpack5/gulp)
webpack5
直接在 webpack.config.js 注册即可
// webpack.config.js
plugins: [
new UnifiedWebpackPluginV5({
appType: 'native',
}),
],gulp
这个配置稍微繁琐一些
// gulpfile.js
const { createPlugins } = require('weapp-tailwindcss-webpack-plugin/gulp')
// 在 gulp 里使用,先使用 postcss 转化 css,触发 tailwindcss 运行,转化 transformWxss,然后再 transformJs, transformWxml
// createPlugins 参数 options 就是本插件的配置项
const { transformJs, transformWxml, transformWxss } = createPlugins()
// 参考顺序
// transformWxss
function sassCompile() {
return gulp
.src(paths.src.scssFiles)
.pipe(sass({ errLogToConsole: true, outputStyle: 'expanded' }).on('error', sass.logError))
.pipe(postcss())
.pipe(transformWxss())
.pipe(
rename({
extname: '.wxss'
})
)
.pipe(replace('.scss', '.wxss'))
.pipe(gulp.dest(paths.dist.baseDir))
}
// transformJs
function compileTsFiles() {
return gulp.src(paths.src.jsFiles, {}).pipe(plumber()).pipe(tsProject()).pipe(transformJs()).pipe(gulp.dest(paths.dist.baseDir))
}
// transformWxml
function copyWXML() {
return gulp.src(paths.src.wxmlFiles, {}).pipe(transformWxml()).pipe(gulp.dest(paths.dist.baseDir))
}
// 注意 sassCompile 在 copyWXML 和 compileTsFiles, 这是为了先触发 tailwindcss 处理,从而在运行时获取到上下文
const buildTasks = [cleanTmp, copyBasicFiles, sassCompile, copyWXML, compileTsFiles]
// 注册默认任务 (串行)
gulp.task('default', gulp.series(buildTasks))具体可以参考 weapp-tailwindcss-gulp-template(gulp打包) 模板项目的配置。
从 v1 迁移
在 2.x 版本中,可以把之前使用的 webpack 插件,全部更换为 UnifiedWebpackPluginV5 插件,不过 vite 插件的导出有一些小变化:
1.x:
import vwt from 'weapp-tailwindcss-webpack-plugin/vite';2.x:
// UnifiedViteWeappTailwindcssPlugin 就是新的插件
import { UnifiedViteWeappTailwindcssPlugin } from 'weapp-tailwindcss-webpack-plugin/vite';另外新的 UnifiedWebpackPluginV5 可以直接从 weapp-tailwindcss-webpack-plugin 引入,同时在新的 UnifiedWebpackPluginV5 中,之前所有的配置项都被继承了过来,只需要用它直接替换原先插件即可。
另外不要忘记把:
"scripts": {
+ "postinstall": "weapp-tw patch"
}添加进你的 package.json 里,然后清除原先的打包缓存之后重新打包运行。
精确转化与忽略
默认对所有 jsx,js,wxml,wxss中出现的tailwindcss运行时工具类进行转化,如果不需要转化可以使用 /*weapp-tw ignore*/ 前置注释。
例如:
<view :class="classArray">classArray</view>
const classArray = [
'text-[30rpx]',
/*weapp-tw ignore*/ 'bg-[#00ff00]'
]此时只有 'text-[30rpx]' 会被转化,'bg-[#00ff00]'被忽视
另外有可能出现的问题,我也写进了 常见问题 中,可以进行参考。
Options 配置项
htmlMatcher
类型: ((assetPath:string)=>boolean)|string|string[]
描述: 匹配 wxml等等模板进行处理的方法
cssMatcher
类型: ((assetPath:string)=>boolean)|string|string[]
描述: 匹配 wxss等等样式文件的方法
jsMatcher
类型: ((assetPath:string)=>boolean)|string|string[]
描述: 匹配 js文件进行处理的方法,用于jsx相关模板
mainCssChunkMatcher
类型: (assetPath:string)=>boolean
描述: 匹配 tailwindcss jit 生成的核心 css chunk 的方法
customRuleCallback
类型: (node: Postcss.Rule, options: Readonly<RequiredStyleHandlerOptions>) => void
描述: 可根据 Postcss walk 自由定制处理方案的 callback 方法
disabled
类型: boolean
描述: 是否禁用该插件,默认为 false,一般用于多平台构建,有些平台比如 h5 不需要开启此插件,所以可以根据环境变量进行禁用。
cssPreflightRange
类型: 'view' | 'all'
描述: 全局dom选择器,只有在这个选择器作用范围内的dom会被注入 cssPreflight 的变量和默认样式。默认为 'view' 即只对所有的 view 和伪元素生效,想要对所有的元素生效,可切换为 'all',此时需要自行处理和客户端默认样式的冲突
replaceUniversalSelectorWith
类型: string | false
描述: 把css中的全局选择器 * 替换为指定值,默认替换为 'view',设置为 false 时不进行替换,此时小程序会由于不认识*选择器而报错
customAttributes
类型: Record<string, string | Regexp | (string | Regexp)[]>
描述: 这是一个重要的配置!
它可以自定义wxml标签上的attr转化属性。默认转化所有的class和hover-class,这个Map的 key为匹配标签,value为属性字符串或者匹配正则数组。如果你想要增加转化的属性,你可以添加 *: (string | Regexp)[] 这样的键值对,使其中属性的转化,在所有标签上生效,更复杂的情况,可以传一个Map实例。
假如你要把 className 通过组件的prop传递给子组件,又或者想要自定义转化的标签属性时,需要用到此配置,案例详见:issue#134 issue#129
customReplaceDictionary
类型: 'simple' | 'complex' | Record<string, string>
描述: 默认为 'complex' 模式,这个配置项,用来自定义转化class名称字典,你可以使用这个选项来简化生成的class
插件中内置了'simple'模式和'complex'模式:
'simple'模式: 把小程序中不允许的字符串,转义为相等长度的代替字符串,这种情况不追求转化目标字符串的一比一绝对等价,即无法从生成结果,反推原先的class'complex'模式: 把小程序中不允许的字符串,转义为更长的代替字符串,这种情况转化前后的字符串是等价的,可以从结果进行反推,缺点就是会生成更长的class导致wxml和wxss这类的体积增大
当然,你也可以自定义,传一个 Record<string, string> 类型,只需保证转化后 css 中的 class 选择器,不会和自己定义的 class 产生冲突即可,示例见dic.ts
minifiedJs
类型: boolean
描述: 是否压缩生成的js文件内容,默认使用环境变量判断: process.env.NODE_ENV === 'production'
cssPreflight
类型: Record<string,string>| false
描述: 在所有 view节点添加的 css 预设,可根据情况自由的禁用原先的规则,或者添加新的规则。 详细用法如下:
// default 默认:
cssPreflight: {
'box-sizing': 'border-box',
'border-width': '0',
'border-style': 'solid',
'border-color': 'currentColor'
}
// result
// box-sizing: border-box;
// border-width: 0;
// border-style: solid;
// border-color: currentColor
// case 禁用所有
cssPreflight: false
// result
// none
// case 禁用单个属性
cssPreflight: {
'box-sizing': false
}
// border-width: 0;
// border-style: solid;
// border-color: currentColor
// case 更改和添加单个属性
cssPreflight: {
'box-sizing': 'content-box',
'background': 'black'
}
// result
// box-sizing: content-box;
// border-width: 0;
// border-style: solid;
// border-color: currentColor;
// background: blacksupportCustomLengthUnitsPatch
类型: ILengthUnitsPatchOptions | boolean
描述: 自从tailwindcss 3.2.0对任意值添加了长度单位的校验后,小程序中的rpx这个wxss单位,由于不在长度合法名单中,于是被识别成了颜色,导致与预期不符,详见:issues/110。所以这个选项是用来给tailwindcss运行时,自动打上一个支持rpx单位的补丁。默认开启,在绝大部分情况下,你都可以忽略这个配置项,除非你需要更高级的自定义。
目前自动检索存在一定的缺陷,它会在第一次运行的时候不生效,关闭后第二次运行才生效。这是因为 nodejs 运行时先加载好了
tailwindcss模块 ,然后再来运行这个插件,自动给tailwindcss运行时打上patch。此时由于tailwindcss模块已经加载,所以patch在第一次运行时不生效,ctrl+c关闭之后,再次运行才生效。这种情况可以使用:
"scripts": {
+ "postinstall": "weapp-tw patch"
}使用 npm hooks 的方式来给 tailwindcss 自动打 patch
使用任意值(arbitrary values)
详见 tailwindcss/using-arbitrary-values 章节
变更日志
常见问题
目前微信开发者工具会默认开启
代码自动热重载 (compileHotReLoad)功能,这个功能在原生开发中表现良好,但在uni-app和taro等等的框架中,存在一定的问题,详见issues#37,所以如果你遇到了此类问题,建议关闭代码自动热重载功能。
Related projects
CLI 工具
weapp-ide-cli: 一个微信开发者工具命令行,快速方便的直接启动 ide 进行登录,开发,预览,上传代码等等功能。
模板 template
如何选择?
假如你仅仅是开发一个小程序 + h5 的组合,那么使用 vscode 模板就足够了
假如你的项目构建的重点平台是 app 那么还是推荐使用 hbuilderx 模板,因为 hbuilderx 自带了一套 app 构建和调试的工具链,可以更好的支持你的开发。
使用uni-app cli进行构建 vscode开发
uni-app-vite-vue3-tailwind-vscode-template
uni-app-vue3-tailwind-vscode-template(不推荐,此版本为webpack5打包vue3,建议使用上面的vite打包vue3的模板)
uni-app-vue2-tailwind-vscode-template
使用hbuilderx 进行构建和开发
uni-app-vue2-tailwind-hbuilder-template(不推荐,此版本收到hbuilderx的限制,无法升级到最新的tailwindcss)
uni-app-vue3-tailwind-hbuilder-template
使用tarojs进行构建 vscode开发
taro-react-tailwind-vscode-template
原生小程序开发模板
weapp-tailwindcss-gulp-template(gulp打包)
weapp-native-mina-tailwindcss-template(webpack打包)
tailwindcss plugin
tailwindcss preset
tailwindcss-miniprogram-preset
Bugs & Issues
目前这个插件正在快速的开发中,如果遇到 Bug 或者想提出 Issue
