一種在 MediaWiki 頁面中引入 Vue 專案或者其他框架的辦法

AurLemon發表於2024-08-29

前言

最近自己的 MediaWiki 網站有渲染列表的需求,但眾所周知,MediaWiki 是基於 jQuery 庫開發的專案,雖然 MediaWiki 官方對於 Vue 等新興前端框架持積極態度,而維基百科在數年前也採用 Vue 進行開發,但是對於解決我們的需求沒有實際的幫助。

另一點是,MediaWiki 對於單獨一個頁面的定製化的做的不太完善,在頁面裡新增 CSS 還需要新增擴充套件(如透過解析器引入 CSS 的 Extension:CSS 或支援在模板名稱空間下新增 CSS 檔案的 Extension:TemplateStyles ),否則只能在 MediaWiki:Common.css 或其他全域性 CSS。而 JavaScript 雖然也是一樣的在 MediaWiki:Common.js 這種全域性 JS 頁面內新增,但也沒有什麼擴充套件支援單獨引入 JS 到頁面內的。另外,即便可以在 MediaWiki 名稱空間新建 .css.js 字尾的頁面以儲存程式碼,但對程式碼的引入也比較麻煩(解決方案就是在全域性 JS 裡面加個分支,判斷是哪個頁面就跳到哪裡去,辦法有點鬼233,好奇可以看我另一個文章)。

(類似的知識庫系統 Wiki.js 框架原生支援對單獨頁面定製化,包括 CSS 和 HTML 標籤新增,雖然 Wiki.js 用起來比較難受而且很多功能拖了很久,但是頁面的客製化還是可以的)

思路

  • 如果你熟悉 Webpack 打包的配置或者理的清楚路徑相關的內容,那就不用看的很仔細啦!

這篇文章有個前提,就是你能完全掌握自己的 MediaWiki,至少要能在網站根目錄新建檔案,並且有足夠的使用者許可權修改 MediaWiki 內部的內容(至少介面管理員)。

那麼說回正題,應該咋實現呢?觀察一下可以發現,前端專案打包檔案結構都是 index.html 配上幾個名為 css 或者 js 或者 images 的資料夾。打包後的 index.html 裡面無非也就這幾樣東西:Vue 的掛載點 #app、打包後的 JS,如 vendor.js 和 app.js、壓縮後的 CSS,如 app.css 之類的。放個我最近打包的專案的 index.html 做為示例:

<!doctype html>
<html lang="">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <link rel="icon" href="/favicon.ico">
        <title>hydcraft-startpage</title>
        <script defer="defer" src="/js/chunk-vendors.db4b2f88.js"></script>
        <script defer="defer" src="/js/app.9d35b8e4.js"></script>
        <link href="/css/app.8be8ea5f.css" rel="stylesheet">
        </head>
    <body>
        <noscript>
            <strong>HydCraft Startpage required JavaScript. Please enable it to continue. :)<br>If you see it in DevTools, Never mind.</strong>
        </noscript>
        <div id="app"></div>
    </body>
</html>

那麼我們是不是要把 MediaWiki 頁面的容器當成 index.html 就好了呢?!在 MediaWiki 的頁面中留好掛載點 #app <div id="app"></div>,引入 JS 和 CSS 檔案就都好了!而 MediaWiki 的文件中,資源載入器剛好就有載入外部檔案的方法。即:

// 給入一個連結和 MIME 型別引數就好了
mw.loader.load( 'http://example.com/mystyles.css?color=blue', 'text/css' ); // 載入 CSS
mw.loader.load( 'http://example.com/myscript.js', 'text/javascript' ); // 載入 JS

// 其實還有個只能引入 Wiki 頁面的方法 importScript('pageName')
importScript('MediaWiki:Script.js'); // 引入 MediaWiki:Script.js 頁面的 JS 檔案

那麼實現起來就很清晰了,只需要在要引入的頁面留好掛載點;把打包完的專案引入,就大功告成了!但是 JS 檔案如果很多一個一個匯入會不會很麻煩?那讓它打包的時候不要分塊不就好了!理論可行開始實現。

實現

假設我希望在 Lemon 頁面載入 Vue 專案程式碼;站點域名為 https://wiki.example.cn;上傳的路徑點為 https://wiki.example.cn/static/list/。

  1. 建立專案,我自己是用 Vue CLI 建了一個 Vue 2 + JS 的專案,但是從實現方式來看就算是 React、Angular 或者是你自己寫的什麼東西都行。

  2. 控制 JS 和 CSS 打包的時候不分塊。由於我是 Vue CLI 建立的專案自然而然就是在 vue.config.js 中改了,如果是 Webpack 直接建的在 webpack.config.js 修改即可,效果一樣。

module.exports = defineConfig({
    productionSourceMap: false,
    transpileDependencies: true,
    publicPath: '/static/list/',    // 這個的控制看步驟二,這個是公共路徑,如果你打包的檔案有字型或者圖片,那麼在 CSS 裡他們的路徑前面會加個這個

    configureWebpack: {
        optimization: {
            splitChunks: false, 
            runtimeChunk: false
        },
        output: {
            filename: "bundle.js",    // JS 輸出的檔名,要改名字可以看你需求改
        },
    },

    css: {
        extract: {
          filename: "styles.css" // CSS 的檔名
      } 
    }
});

另外,如果希望儘量減少打包出的 JS 檔案(如果有其他的會單獨建立一個 js 資料夾),那麼專案裡引入元件的時候就不要使用動態引入,使用靜態引入。

  1. 確定要上傳的地方。
    此時,把打包好的檔案上傳到你要上傳的地方,把步驟一中的配置檔案的 publicPath 修改成對應的路徑:

如果是 MediaWiki 站點的目錄,那麼不需要把 URL 全部寫出來(畢竟呼叫同域的資源)。舉個例子,我的站點域名是 www.example.wiki,對應的路徑是 /www/wwwroot/example.wiki。我打算把打包後的內容上傳到 /www/wwwroot/example.wiki/static/ 目錄下,對應的 URL 即 www.example.wiki/static/ 下。那麼 publicPath 就需要改成 /static/,上傳後的 JS 檔案就是 www.example.wiki/static/bundle.js。CSS 檔案同理。

如果是其他的站點,那麼則需要把 URL 寫全了。舉個例子,我把打包後的東西放 https://static.example.com/wiki/,那麼 publicPath 就需要改成 https://static.example.com/wiki/。呼叫 JS 檔案的時候也就是 https://static.example.com/wiki/bundle.js,CSS 檔案也同理。不過,如果是外部站點,那麼需要注意下跨域的配置是否正常,一般建議直接放到 MediaWiki 站點內部(因為我就這麼幹的,省事,都可以啦看你自己)。

當然!如果你瞭解 publicPath 和各種路徑之間的關係,那就不用那麼複雜的看這個介紹,自己相應的修改即可。

  1. 打包和上傳檔案到對應的位置。

  2. 在 MediaWiki 配置相應的內容。

我們需要在 Lemon 頁面新增內容,那麼首先透過原始碼編輯,在這個頁面新增一個<div id="app"></div>掛載點(主要看打包後的 index.html 裡面是什麼元素,如果你修改了預設掛載點名字那這裡也需要改。一般 Vue 是 #app,React 是 #root)。隨後在 MediaWiki:Common.js(如果你不想放全域性裡面呼叫,可以放到其他頁面去,具體可以看另一篇文章)新增以下內容:

mw.loader.load( 'https://wiki.example.cn/static/list/bundle.js', 'text/javascript' );
mw.loader.load( 'https://wiki.example.cn/static/list/styles.css', 'text/css' );

這裡我寫了兩條,一個是 bundle.js 另一個是 styles.css。實際上就是把打包後的 index.html 內部呼叫的 CSS 和 JS 變成 MediaWiki 呼叫外部資源的方法就可以了!

當然,其實不用每次都看 index.html 裡面的內容,一般打包完就會告訴你有幾個檔案,看那裡基本就能確定了。

此時就大功告成了,直接開啟對應的頁面檢查結果就好了。

(字型和圖片不用引入,因為打包後都在 JS 或者 CSS 裡了,他們的路徑是跟著 publicPath 來的)

後話

想不到什麼要說的,如果上傳了一次以後又覆蓋上傳了,在對應的頁面測試的時候記得 Ctrl+F5 重新整理快取測試(?)。

相關文章