一种在 MediaWiki 页面中引入 Vue 或者其他项目的办法

前言

最近自己的 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 文件如果很多一个一个导入会不会很麻烦?那让它打包的时候不要分块不就好了!理论可行开始实现。

总的来说:用 npm(或者别的什么包管理器)新建好一个项目,打包好直接丢到一个地方去,然后通过 MediaWiki 提供的方法引用那些文件就好。

实现

假设我希望在 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 刷新缓存测试(?)。

posted @ 2024-08-29 06:33  AurLemon  阅读(40)  评论(0编辑  收藏  举报