Пробросить window и document в Vue при запуске через терминал NodeJS
В nodejs запускаю webpack, сервер polka (minimal express.js) и далее экземпляр Vue. Один компонент ругается на отсутствие window и document. Как в Nodejs можно создать эти глобальные переменные? Вроде есть пакеты (JSDOM например) которые позволяют создавать DOM. Пробовал через DefinePlugin в конфигурации WEBPACK делать глобальную переменную, но Vue не видит ее...
build.js
const fs = require('fs'),
path = require('path'),
polka = require('polka')
vueSR = require('vue-server-renderer');
let renderer;
const app = polka();
require('./ssr/setup-dev-server.js')(app, {
render(bundle) {
renderer = vueSR.createBundleRenderer(bundle);
renderer.renderToString().then(html => {
fs.writeFileSync("./ssr/cache/"+process.argv[2]+".tmp", JSON.stringify(html))
}).catch((e) => {
console.log(e)
fs.appendFileSync("./ssr/logs/errors.log", `\n${e.toString()}`)
fs.writeFileSync("./ssr/cache/"+process.argv[2]+".tmp", '')
})
},
});
setup-dev-server
/* eslint-disable no-console */
const path = require('path'),
webpack = require('webpack'),
MFS = require('memory-fs');
const serverConfig = require('./webpack/webpack-server');
module.exports = (app, opts) => {
const
serverCompiler = webpack(serverConfig),
mfs = new MFS(),
serverBundlePath = path.join(serverConfig.output.path, 'vue-ssr-server-bundle.json');
serverCompiler.outputFileSystem = mfs;
serverCompiler.run((err, stats) => {
if (err) throw err;
/* stats = stats.toJson();
stats.errors.forEach(err => console.error(err));
stats.warnings.forEach(err => console.warn(err));*/
opts.render(JSON.parse(mfs.readFileSync(serverBundlePath, 'utf-8')));
});
};
webpack-server.js
const path = require('path'),
{ createConfig } = require('./webpack-base.js'),
{ DefinePlugin } = require('webpack'),
VueSSRServerPlugin = require('vue-server-renderer/server-plugin');
const baseConfig = createConfig('server');
const serverConfig = Object.assign({}, baseConfig, {
target: 'node',
entry: './ssr/entry/server.js',
output: {
...baseConfig.output,
libraryTarget: 'commonjs2',
filename: 'server-bundle.js',
path: path.resolve(process.cwd(), 'dist/server'),
},
externals: Object.keys(require('../../../../package.json').dependencies),
plugins: (baseConfig.plugins || []).concat([
new DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
window: 'undefined',
}),
new VueSSRServerPlugin(),
]),
});
serverConfig.module.rules = (baseConfig.module.rules || []).concat([
{
test: /\.(styl(us)?|css|less|sass|scss|sss)$/,
loader: 'null-loader',
},
]);
module.exports = serverConfig;
webpack-base.js
const path = require('path'),
{ VueLoaderPlugin } = require('vue-loader');
exports.createConfig = (runtimeEnv) => {
const vueLoader = {
test: /\.vue$/,
loader: 'vue-loader',
options: {},
};
const config = {
devtool: false,
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
output: {
publicPath: '/dist/',
filename: '[name].[chunkhash:8].js',
chunkFilename: '[name].[chunkhash:8].js',
},
module: {
rules: [
// source files
{
test: /\.js$/,
loader: 'babel-loader',
// needed for vue-loader to correctly import modules' components
exclude: file => /node_modules/.test(file) && !/\.vue\.js/.test(file),
},
vueLoader
],
},
resolve: {
extensions: ['.js', '.vue', '.json'],
modules: [
'node_modules',
process.cwd(),
],
},
performance: {
hints: process.env.NODE_ENV === 'production' ? 'warning' : false,
},
plugins: [
new VueLoaderPlugin(),
],
stats: {
all: false,
colors: true,
errors: true,
hash: true,
timings: true,
version: true,
}
};
if (process.env.NODE_ENV === 'development') {
vueLoader.options.cacheDirectory = path.resolve(process.cwd(), 'node_modules/.cache/vue-loader-cache');
vueLoader.options.cacheIdentifier = runtimeEnv;
}
return config;
};
server.js
import createApp from './app';
export default context => {
return createApp(context);
};
Ответы (1 шт):
Автор решения: Денис Григоров
→ Ссылка
Решение:
Помог пакет browser-env.
В месте создания экземпляра сервера, нужно вызывать метод require('browser-env')();
Тогда появится полноценный виртуальный DOM и плагины, использующие DOM заработают