koa-web-webpack
Version:
koa-web webpack
200 lines (179 loc) • 4.92 kB
JavaScript
;
const fs = require("fs");
const webpack = require('webpack');
const webpackDev = require('webpack-dev-middleware');
const { VueLoaderPlugin } = require('vue-loader');
const path = require("path");
const crypto = require("crypto");
const thisPath = path.dirname(__filename);
class App {
// webpack解析
static webpacks = {};
static debug = true;
static vuePath = thisPath + "/vue.js";
static cachePath = `${process.cwd()}/.cache/webpack/`;
static cacheStr = fs.readFileSync(`${thisPath}/cache.js`).toString();
static async apply(middleware, req, res) {
const _send = res.send;
return new Promise((resolve, reject) => {
try {
res.send = function () {
_send.apply(res, arguments) && resolve(false);
};
middleware(req, res, resolve.bind(null, true));
} catch (error) {
reject(error);
}
});
}
/**
* 删除文件夹
* @param {*} path
*/
static delDir(path) {
let files = [];
if (fs.existsSync(path)) {
files = fs.readdirSync(path);
files.forEach((file, index) => {
let curPath = path + "/" + file;
if (fs.statSync(curPath).isDirectory()) {
App.delDir(curPath);
} else {
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
}
}
/**
* 创建文件夹
* @param {*} path
* @returns
*/
static mkdir (path = '') {
if (fs.existsSync(path)) {
if (fs.statSync(path).isDirectory()) {
return true;
}
}
path = path.replace(/[\\]/g, "/");
let isWin = path[1] === ':';
let pos = path.lastIndexOf("/");
if (pos >= 0) {
path = path.substring(0, pos);
}
let pathTmp = "";
let pathList = path.split("/");
if (isWin && pathList.length > 0) {
pathTmp = pathList[0];
delete pathList.shift();
}
try {
for (const i in pathList) {
pathTmp += "/" + pathList[i];
if (fs.existsSync(pathTmp)) {
if (fs.statSync(pathTmp).isFile()) {
return false;
}
} else {
fs.mkdirSync(pathTmp);
}
}
} catch (e) {
return false;
}
return true;
}
/**
* 获取webpack数据
* @param {*} rootPath
* @param {*} subPath
* @param {*} hd
*/
static async setWebpack(rootPath, subPath, hd) {
if (App.webpacks[subPath] === undefined) {
rootPath = rootPath.replace(/\\/g, '/');
let vueFile = `${rootPath}${subPath}.vue`;
if (!(fs.existsSync(vueFile) && fs.statSync(vueFile).isFile())) {
return;
}
let spMd5 = crypto.createHash('md5').update(subPath).digest("hex").substring(8, 24);
let spCacheFile = `${App.cachePath}${spMd5}.js`;
if (!App.mkdir(App.cachePath)) {
return hd.ctx.body = "无法创建webpack缓存目录";
}
let cacheStr = App.cacheStr.replace('__VUE__', `${rootPath}${subPath}.vue`);
fs.writeFileSync(spCacheFile, cacheStr);
let config = {
entry: spCacheFile,
mode: 'development',
output: {
filename: `${subPath}.js`
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
},
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.js?$/,
loader: 'babel-loader'
}
]
},
plugins: [
new VueLoaderPlugin()
],
};
if (!App.debug) {
// 启用调试
config['mode'] = 'production';
config['stats'] = 'errors-only';
}
App.webpacks[subPath] = webpackDev(webpack(config), {});
}
await App.apply(App.webpacks[subPath], hd.ctx.req, Object.assign(hd.ctx.res, {
send: content => {
return hd.ctx.body = content;
}
}));
}
static async run (setMid, setData, setLoad) {
App.delDir(App.cachePath);
setMid('js', async hd => {
let hdData = hd.data;
let subPath = hdData.ctxDir;
if (hdData.domainPath !== '') {
subPath = `${hdData.domainPath}/${subPath}`;
}
let hdPath = `${hdData.rootPath}${subPath}`;
let wpPath = `${hdPath}.vue`;
if (!fs.existsSync(wpPath) || !fs.statSync(wpPath).isFile()) {
return;
}
await App.setWebpack(hdData.rootPath, subPath, hd);
});
setLoad((koaApp, config) => {
if (typeof config.webpackDebug === 'boolean') {
App.debug = config.webpackDebug;
}
});
};
}
module.exports = App.run;