一种在 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/。
-
创建项目,我自己是用 Vue CLI 建了一个 Vue 2 + JS 的项目,但是从实现方式来看就算是 React、Angular 或者是你自己写的什么东西都行。
-
控制 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 文件夹),那么项目里引入组件的时候就不要使用动态引入,使用静态引入。
- 确定要上传的地方。
此时,把打包好的文件上传到你要上传的地方,把步骤一中的配置文件的 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 和各种路径之间的关系,那就不用那么复杂的看这个介绍,自己相应的修改即可。
-
打包和上传文件到对应的位置。
-
在 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 刷新缓存测试(?)。