@budingxiaocai/pages-webpack-plugin
Version:
用于自动化多页面应用构建的 Webpack 插件 / Webpack plugin for automating the construction of multi page applications
100 lines (80 loc) • 3.09 kB
JavaScript
const fs = require('fs');
const path = require('path');
const glob = require('fast-glob');
const EntryPlugin = require('webpack/lib/EntryPlugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
class PagesPlugin {
constructor(options = {}) {
this.options = options;
}
apply(compiler) {
const options = this.options;
const scanDir =
(typeof options.scanDir === 'string' && options.scanDir) ||
path.join(compiler.context, 'src');
delete options.scanDir;
const entryName =
(typeof options.entryName === 'string' && options.entryName) ||
'index.{vue,tsx,jsx,html}';
delete options.entryName;
// 伪静态
let htaccess = `location / {
try_files $uri $uri.html =404;
}`;
const pageDirs = glob.sync('**', {
onlyDirectories: true,
absolute: true,
nocase: true,
cwd: scanDir
});
pageDirs.forEach((dir) => {
let currentEntryName;
let currentWebpackOptions;
if (fs.existsSync(path.join(dir, '.pagerc.json'))) {
// 获取单个目录的配置
const { entryName, options } = JSON.parse(
fs.readFileSync(path.join(dir, '.pagerc.json'), 'utf-8')
);
if (typeof entryName === 'string' && entryName !== '') currentEntryName = entryName;
currentWebpackOptions = options;
}
const entryFile = glob.sync(currentEntryName || entryName, {
absolute: true,
nocase: true,
cwd: dir
});
if (entryFile.length !== 1) return;
let pageName = path.basename(dir);
let pagePath =
path.dirname(path.relative(scanDir, dir).split(path.sep).join('/')) + '/';
if (pageName.startsWith('[') && pageName.endsWith(']')) {
pageName = '@' + pageName.slice(1, -1) + '@';
htaccess += '\r\n\r\n';
htaccess += `location ~ ^/${pagePath}([^/]+)/?$ {
rewrite ^/${pagePath}([^/]+)/?$ /${pagePath}${pageName}.html?${pageName.slice(1, -1)}=$1 break;
}`;
}
if (pagePath === './') pagePath = '';
new EntryPlugin(compiler.context, entryFile[0], pageName).apply(compiler);
new HtmlWebpackPlugin(
Object.assign(
{
chunks: [pageName],
filename: pagePath + pageName + '.html'
},
currentWebpackOptions,
options
)
).apply(compiler);
});
compiler.hooks.afterEmit.tapAsync('PagesPlugin', (compilation, callback) => {
fs.writeFileSync(
path.join(compilation.outputOptions.path, '.htaccess'),
htaccess,
'utf-8'
);
callback();
});
}
}
module.exports = PagesPlugin;