如何正确创建 wp enqueue 和函数脚本来运行 vite 前端

art*_*med 2 php wordpress vite

I am running twenty-twentythreetheme of WordPress at the moment I have created a default vite Vue project inside my themes folder. I have not found much tutorials online that match my use case.

I want to run the vite frontend on my WordPress website. The following is my enqueue script and functions.php

Functions.php

    <?php
/**
 * Vue Twenty Seventeen Child Theme Functions and Definitions.
 * Requires Twenty Seventeen and only works in WordPress 4.7 or later.
 *
 * @package WordPress
 */

 // includes for the callbacks.
include_once( get_stylesheet_directory() . '/enqueue-scripts.php' );

/* hooks and filters */

?>
Run Code Online (Sandbox Code Playgroud)

enqueue-scripts.php


function enqueue_vue_assets() {
 wp_enqueue_script( 'app', get_template_directory_uri() . '/example/dist/assets/index-ec461b82.js', array(), '1.0', true );
 wp_enqueue_style( 'app', get_template_directory_uri() . '/example/dist/assets/index-fc5f319f.css', array(), '1.0' );
}
add_action( 'wp_enqueue_scripts', 'enqueue_vue_assets' );

?> 
Run Code Online (Sandbox Code Playgroud)

These files are inside my twenty-twentythreetheme folder. The example is my vite project. I have not made any configurations in vite. Do I need to make any? What changes do I need to make in my enqueue script and functions script.

Also the twentytwentythree theme has mostly .html files on its frontend which I have wiped and added div id=app that should come from the app.vue.

jos*_*oto 5

如果您希望Vitehot在任何本地 WordPress 主题构建中通过 file 方法编译资源并自动渲染浏览器。下面是使用Chris Page 的自定义 php 类来处理 Wordpress 中的 Vite的工作方法。

按照以下步骤让 Vite 在 Wordpress 主题中正常运行...

(下面的主题示例twentytwentythree,但这适用于任何 WordPress 主题)

将 PHP 实现到主题中

请参阅下面的 Vite php 类Vite.lib.php代码...

克里斯·佩奇 (Chris Page) 的要点版本

<?php

class Vite {

    /**
     * Flag to determine whether hot server is active.
     * Calculated when Vite::initialise() is called.
     *
     * @var bool
     */
    private static bool $isHot = false;

    /**
     * The URI to the hot server. Calculated when
     * Vite::initialise() is called.
     *
     * @var string
     */
    private static string $server;

    /**
     * The path where compiled assets will go.
     *
     * @var string
     */
    private static string $buildPath = 'build';

    /**
     * Manifest file contents. Initialised
     * when Vite::initialise() is called.
     *
     * @var array
     */
    private static array $manifest = [];

    /**
     * To be run in the header.php file, will check for the presence of a hot file.
     *
     * @param  string|null  $buildPath
     * @param  bool  $output  Whether to output the Vite client.
     *
     * @return string|null
     * @throws Exception
     */
    public static function init(string $buildPath = null, bool $output = true): string|null
    {

        static::$isHot = file_exists(static::hotFilePath());

        // have we got a build path override?
        if ($buildPath) {
            static::$buildPath = $buildPath;
        }

        // are we running hot?
        if (static::$isHot) {
            static::$server = file_get_contents(static::hotFilePath());
            $client = static::$server . '/@vite/client';

            // if output
            if ($output) {
                printf(/** @lang text */ '<script type="module" src="%s"></script>', $client);
            }

            return $client;
        }

        // we must have a manifest file...
        if (!file_exists($manifestPath = static::buildPath() . '/manifest.json')) {
            throw new Exception('No Vite Manifest exists. Should hot server be running?');
        }

        // store our manifest contents.
        static::$manifest = json_decode(file_get_contents($manifestPath), true);

        return null;
    }

    /**
     * Enqueue the module
     *
     * @param string|null $buildPath
     *
     * @return void
     * @throws Exception
     */
    public static function enqueue_module(string $buildPath = null): void
    {
        // we only want to continue if we have a client.
        if (!$client = Vite::init($buildPath, false)) {
            return;
        }

        // enqueue our client script
        wp_enqueue_script('vite-client',$client,[],null);

        // update html script type to module wp hack
        Vite::script_type_module('vite-client');

    }

    /**
     * Return URI path to an asset.
     *
     * @param $asset
     *
     * @return string
     * @throws Exception
     */
    public static function asset($asset): string
    {
        if (static::$isHot) {
            return static::$server . '/' . ltrim($asset, '/');
        }

        if (!array_key_exists($asset, static::$manifest)) {
            throw new Exception('Unknown Vite build asset: ' . $asset);
        }

        return implode('/', [ get_stylesheet_directory_uri(), static::$buildPath, static::$manifest[$asset]['file'] ]);
    }

    /**
     * Internal method to determine hotFilePath.
     *
     * @return string
     */
    private static function hotFilePath(): string
    {
        return implode('/', [static::buildPath(), 'hot']);
    }

    /**
     * Internal method to determine buildPath.
     *
     * @return string
     */
    private static function buildPath(): string
    {
        return implode('/', [get_stylesheet_directory(), static::$buildPath]);
    }

    /**
     * Return URI path to an image.
     *
     * @param $img
     *
     * @return string|null
     * @throws Exception
     */
    public static function img($img): ?string
    {

        try {

            // set the asset path to the image.
            $asset = 'resources/img/' . ltrim($img, '/');

            // if we're not running hot, return the asset.
            return static::asset($asset);

        } catch (Exception $e) {

            // handle the exception here or log it if needed.
            // you can also return a default image or null in case of an error.
            return $e->getMessage(); // optionally, you can retrieve the error message

        }

    }

    /**
     * Update html script type to module wp hack.
     *
     * @param $scriptHandle bool|string
     * @return mixed
     */
    public static function script_type_module(bool|string $scriptHandle = false): string
    {

        // change the script type to module
        add_filter('script_loader_tag', function ($tag, $handle, $src) use ($scriptHandle) {

            if ($scriptHandle !== $handle) {
                return $tag;
            }

            // return the new script module type tag
            return '<script type="module" src="' . esc_url($src) . '" id="' . $handle . '-js"></script>';

        }, 10, 3);

        // return false
        return false;

    }

}
Run Code Online (Sandbox Code Playgroud)

将此类Vite.lib.php文件放置lib在本地twentytwentythree主题目录的文件夹中,然后Vite.lib.phpfunctions.php.

然后,您想要创建一个主题 php 类Theme.lib.php来处理将脚本和 css 排队以与 Vite 一起使用...

<?php

class Theme {

    public function __construct()
    {
        
        // enqueue admin styles scripts
        add_action('wp_enqueue_scripts', [ $this, 'enqueue_styles_scripts' ], 20);
        
    }
    
    /**
     * @return void
     * @throws Exception
     */
    public function enqueue_styles_scripts(): void
    {

        // enqueue the Vite module
        Vite::enqueue_module();

        // register theme-style-css
        $filename = Vite::asset('resources/scss/theme.scss');

        // enqueue theme-style-css into our head
        wp_enqueue_style('theme-style', $filename, [], null, 'screen');

        // register theme-script-js
        $filename = Vite::asset('resources/js/theme.js');

        // enqueue theme-script-js into our head (change false to true for footer)
        wp_enqueue_script('theme-script', $filename, [], null, false);

        // update html script type to module wp hack
        Vite::script_type_module('theme-script');

    }

}

new Theme();
Run Code Online (Sandbox Code Playgroud)

然后在你的function.php, requireTheme.lib.php之后Vite.lib.php像这样......

<?php

// require libs
require_once(__DIR__ . '/lib/Vite.lib.php');
require_once(__DIR__ . '/lib/Theme.lib.php');
Run Code Online (Sandbox Code Playgroud)

使用 NPM 将 Vite 安装到主题中

实现上述 php 后,让我们package.json在本地主题目录中重新开始。

当Vite运行起来后,您可以稍后重新添加Vue和其他依赖项

package.json以下是在 Wordpress 中使用 Vite 启动项目的基本样板...

{
  "private": true,
  "scripts": {
    "dev": "vite",
    "watch": "npm run dev",
    "build": "vite build",
    "production": "vite build"
  },
  "devDependencies": {
    "sass": "^1.63.6",
    "vite": "^4.4.3",
    "laravel-vite-plugin": "^0.7.8"
  },
  "dependencies": {

  }
}
Run Code Online (Sandbox Code Playgroud)

laravel-vite-plugin您会注意到我们在我们的 中使用了package.json这个 Laravel Vite 插件,可以非常轻松地在我们的 中配置资源和构建目录vite.config.js,并监视整个主题中的 php 文件更改!

请参阅下面的工作,将我们的和资源vite.config.js编译到构建文件夹。该文件也位于您的本地主题目录中,与您的...相同theme.csstheme.jsvite.config.jspackage.json

import {defineConfig} from "vite";
import laravel from 'laravel-vite-plugin';

export default defineConfig(() => ({
    base: '',
    build: {
        emptyOutDir: true,
        manifest: true,
        outDir: 'build',
        assetsDir: 'assets'
    },
    plugins: [
        laravel({
            publicDirectory: 'build',
            input: [
                'resources/js/theme.js',
                'resources/scss/theme.scss'
            ],
            refresh: [
                '**.php'
            ]
        })
    ],
    resolve: {
        alias: [
            {
                find: /~(.+)/,
                replacement: process.cwd() + '/node_modules/$1'
            },
        ]
    }
}));
Run Code Online (Sandbox Code Playgroud)

resources在我们安装 NPM 和安装 Vite build 之前,您需要在本地主题目录中创建一个文件夹。然后在resources文件夹内创建这些img, scss, js目录,然后创建空theme.scss, theme.js文件,结构如下......

在此输入图像描述

现在我们准备在我们的package.json配置上运行 NPM 安装。

在主题目录中打开终端并运行此命令...

npm install
Run Code Online (Sandbox Code Playgroud)

此命令安装我们的开发依赖项并创建我们的node_modules库根供应商文件,再加上创建一个package-lock.json文件,所以我们的主题目录现在看起来像这样......

在此输入图像描述

初始Vite项目构建

现在Vite已经安装完毕,我们准备构建我们的Vite项目了。

在我们运行 Vite 构建之前,如果您在本地访问您的站点,您会发现出现致命错误。这是因为我们还没有生成Vite清单json文件。Vitemanifest.json 处理我们的resources文件和缓存无效的 build/assets文件之间的链接。

好的,让我们用 Vite 构建我们的资源,这样您就可以开始创造一些魔法了!

在本地主题目录中,首先运行此命令...

npm run build
Run Code Online (Sandbox Code Playgroud)

命令应返回此日志...

在此输入图像描述

npm run build如果您是启动一个全新的 Vite 项目,则只需初始运行一次。此命令最初会创建您的build文件夹build/manifest.jsonbuild/assets/..缓存已损坏的文件。

npm run build请注意,每次您想要构建生产缩小构建资产和生产时,都需要再次使用manifest.json

npm run build第一次运行后,您的主题目录将如下所示......

在此输入图像描述

如果您访问本地站点,您会发现致命错误已经消失,并且生产版本theme.csstheme.js正常工作!

如果您的本地主题工作正常,没有错误,您可以检查源代码,您将看到theme.csstheme.js在 html 中像这样排队...

<link href="http://localhost/wp-content/themes/vite-wordpress/build/assets/theme-716126ae.css" rel="stylesheet" id="theme-style-css" type="text/css" media="screen"> 
Run Code Online (Sandbox Code Playgroud)
<script src="http://localhost/wp-content/themes/vite-wordpress/build/assets/theme-13161a16.js" type="module" id="theme-script-js"></script>
Run Code Online (Sandbox Code Playgroud)

上面的排队输出正是您希望它在您的环境中呈现的staging样子productionhot这是当我们的Vite本地开发文件不存在时的预期输出!

启动Vite本地dev js服务器

最后,我们准备启动史诗般的 Vite 本地 js 服务器和hot文件,以实现超快速的开发编译和自动浏览器资源渲染,而无需刷新浏览器!

如果您最初构建了 Vitebuild文件,您现在可以运行下面的命令来启动本地 Vite js 服务器和hot文件以监视主题中的任何保存更改。

npm run dev
Run Code Online (Sandbox Code Playgroud)

该命令应该返回这样的日志,并显示 Vite dev 本地 js 服务器正在运行...

在此输入图像描述

您会注意到hot您的目录中现在存在一个文件build...

在此输入图像描述

如果您现在刷新本地 WordPress 站点,会注意到我们的排队theme.csstheme.jshtml 已更改为这样...

<link href="http://127.0.0.1:5173/resources/scss/theme.scss" rel="stylesheet" id="theme-style-css" type="text/css" media="screen">
Run Code Online (Sandbox Code Playgroud)
<script src="http://127.0.0.1:5173/resources/js/theme.js" type="module" id="theme-script-js"></script>
Run Code Online (Sandbox Code Playgroud)

您还会注意到<head>我们的 Vite 客户端 js 模块中加载了一个额外的脚本。该脚本正在处理hot文件观察器,以了解对主题中的文件所做的任何更改。

<script src="http://127.0.0.1:5173/@vite/client" type="module" id="vite-client-js"></script>
Run Code Online (Sandbox Code Playgroud)

现在我们正在运行 Vite 开发服务器,您可以开始向您的资源文件添加theme.css代码theme.js

每次您点击保存资源文件时,Vite 都会编译您的项目,并且更改将在您的浏览器中自动运行/更新,无需刷新!如果您编辑并保存 PHP,也会发生同样的情况。

安装 NPM 包和依赖项

当本地 Vite dev js 服务器仍在运行时,您可以通过新的终端窗口安装 Vue 和其他软件包,而无需停止当前的 Vite dev js 服务器观察程序。

生产构建和部署

一旦您准备好进行生产构建,请确保您已退出 Vite dev js 服务器并且不再运行...

npm run build然后在您的主题目录中重新运行,以在您的build目录中构建缓存无效的生产文件。同步build目录stagingproduction环境。

确保functions.phpVite.lib.phpTheme.lib.php也部署到您的stagingproduction环境中,以便build/assets在您的主题中工作。

使用位于resources/img

使用主题build文件夹中的图像,这些图像是从该resources/img目录编译到该build/assets目录的图像。

用法php是...

<img src="<?=Vite::img('example.png')?>" alt="Example" />
Run Code Online (Sandbox Code Playgroud)

而且scss用法是...

BODY {
  background-image: url(../img/example.png);
}
Run Code Online (Sandbox Code Playgroud)