仔细看一下官方插件HelloWorld的源码,你会发现其中就这么一句话:\Typecho\Plugin::factory('admin/menu.php')->navBar = __CLASS__.'::render';,然后你搜索admin目录,最终发现调用竟然是:\Typecho\Plugin::factory('admin/menu.php')->navBar(),于是你就可以知道,最快写插件,而且侵入式不强的插件方法就是类似这样的写法。

例如:

//前台入口只有一个:index.php,所以需要直接这样写
\Typecho\Plugin::factory('index.php')->showSiteName = __CLASS__.'::showSiteName';

在模板中调用:

\Typecho\Plugin::factory('index.php')->showSiteName()

是不是发现自己会写插件了?
而且,它的优点时,只在激活的时候注册一下,不会每次都加载(因为你也不需要每次都加载)。

但如果是用类似\Typecho\Plugin::factory('Widget_Archive')->beforeRender = [new self,'contentExtend'];这样的方法,只要调用到了Widget\Archive类,几乎都会执行一次,效率就低了。所以应该根据实际情况使用插件

昨天在 如何使用tailwindcss来制作皮肤 一文中有写到如何利用 tailwindcss 来制作皮肤,这个当然没有什么难度,但制作皮肤最重要的是什么?那就是即时预览,于是我就想到了vite,为什么不用webpack呢?主要还是由于他太重了!!!!

方法也不算难,而且用了vite后,还可以做一次打包,上篇文章中提到的css无法加版本号的问题也就解决了。
OK,让我们开始进行尝试吧

# 引入 postcss是为了处理类似引用文章中提到的npx tailwindcss -i in -o out --watch
yarn add -D vite tailwindcss postcss autoprefixer
# 生成相应的tailwindcss的config文件,这里就不再多说了
# 生成相应的vite.config.js

这里比较复杂的或者有难度的其实就是这个vite.config.js以及在代码里如何配置,可以参考:官方文档之后端集成
即:
1、增加manifest的配置为true
2、在当前皮肤全局引入的地方加上(这里面是有问题的,我等会单独讲

<script type="module" src="http://localhost:5173/@vite/client"></script>
<script type="module" src="http://localhost:5173/main.js"></script>

3、写一个php的函数,用于处理manifest中css路径(目前我们假设就只处理Css和JS),代码类似如下:

function manifest($name){
    $f = json_decode(file_get_contents(__DIR__.'/dist/manifest.json'),true);
    return "dist/".$f[$name]['file'];
}
4、简单的在模板目录下写一个app.js,内容可以就一行,比如:

import './style.css' ; //这个就是写了tailwind配置的那个Css文件

下面,我们来详细说说,如果按照官方文档,估计是跑不起来的,我原来踩的坑也就在这里,即那个main.js,其实找不到,也无法找到,这就是typecho项目和其他单文件项目的不同之处,后面我找了文档,发现他的入口文件就是main.js的路径,所以,如果我的入口文件是 usr/themes/xxx/app.js, 那么,上面的http://localhost:5173/main.js就需要改为:http://localhost:5173/usr/themes/xxx/app.js,否则将报404错误

最后,附上详细的vite.config.js内容

import {resolve} from "path";
import {defineConfig, loadEnv} from "vite";

export default defineConfig(({command, mode}) => {
    //如果有这一行,就可以加载根目录下的.env文件,一般可以不用
    const env = loadEnv(mode, process.cwd(), "");
    return {
        base: "/",
        build: {
            manifest: true,
            rollupOptions: {
                input: resolve(__dirname, "usr/themes/xxx/app.js"),
                // input: {
                //     main: resolve(__dirname, "usr/themes/xxx/app.js"),
                // }
            },
            outDir: resolve(__dirname, "usr/themes/xxx/dist"),
            cssCodeSplit: false,
            chunkSizeWarningLimit: 60000,
        },
        css: {
            postcss: {
                plugins: [
                    require('tailwindcss'),
                    require('autoprefixer')
                ]
            }
        }
    };
});

tips:

  • 注意上面的input,有两种写法,默认写法是生成和你的js同名的文件。如果加了entrypoint的入口,就会生成和你entrypoint同名的js文件,这里要记住。
  • outDir,最好是空目录,因为vite生成的新文件的时候,会优先清除所有的其他文件,我第一次生成在指定目录里的时候把图片什么的都干掉了
  • 在全局引用的PHP文件里应该要加上 @if($_SERVER['HTTP_HOST']) 来进行判断,这样即使上线也不用改代码啦~(记得把css和JS分开。),比如我用了blade后,就是<link rel="stylesheet" href="@asset(manifest('style.css'))"/> , so easy !

现在tailwindcss几乎已经是标配了,因为他的优点比较明显,类似语义化的类,同时支持@apply来扩展自己的方法,如果再基于自己的cli命令,还能生成最小化的tailwindcss,比如我当前使用的皮肤,只有12K,关键这还是没有压缩的。

参考:https://www.tailwindcss.cn/docs/installation

现在开始使用:

# 官网推荐,如果你只是自己随便用用,就只要安装tailwindcss就行了 (建议直接在根目录下运行,这样以后的代码可以复用)
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
# 生成tailwind.config.js
npx tailwindcss init

生成后的tailwind.config.js类似这样:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
      //指定themes下的文件,一般都是php后缀
      "./usr/themes/**/*.{php,blade.php}"
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

然后在要修改的皮肤下的app.css添加tailwind的基础css,例如皮肤根目录一下的style.css

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

再运行

npx tailwindcss -i ./usr/themes/[目录]/style.css -o ./usr/themes/[目录]/assets/css/app.css --watch

这时候就可以相当于webpack的watch了。
还是非常方便的,只是有几缺点:

  • header中引入的css,只能是app.css,而且默认没有带上版本号,如果客户端做了缓存,下次更新的时候可能不会更新
  • 无法象vite 那样自动refresh,但这不是当前内容。后面看怎么利用vite/webpack来做refresh看看,实在不行browser-sync也能解决。

使用typecho的时候,看着一堆<?php echo xxx;?>感觉非常不舒服,再加上用laravel很久了,所以直接尝试接入blade模板。事实上,在没有使用laravel前,用Yii进行开发的时候,我其实也已经使用blade来替换yii自带的模板。

---先写这么多,代表项目跑起来了。哈哈