在<style></style>
文件中添加.vue
时会发生这种情况。
[Vue warn]: Error in beforeCreate hook: "ReferenceError: document is not defined"
我主要根据教程站点编写代码。 https://github.com/vuejs/vue-hackernews-2.0/
src / App.vue
<template>
<div class="red">Hello from App.vue</div>
</template>
<script>
export default { name: "App" }
</script>
<style lang="scss" scoped> <-- Without style works well...
.red { color: red; }
</style>
src / app.js
import Vue from 'vue'
import App from './App.vue'
export function createApp() {
let app = new Vue({
render: h => h(App)
})
}
return { app }
}
src / entry-server.js
import { createApp } from './app'
export default context => {
return new Promise((resolve, reject) => {
const { app } = createApp()
resolve(app)
})
}
src / entry-client.js
import { createApp } from './app'
const { app } = createApp()
app.$mount('#app')
webpack.config.js
const path = require('path')
const webpack = require('webpack')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const env = process.env.NODE_ENV || 'development'
const isProd = env === 'production'
const baseConfig = {
mode: env,
devtool: isProd
? false
: 'source-map',
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/dist/',
filename: '[name].js'
},
module: {
noParse: /es6-promise\.js$/,
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'style-loader',
'css-loader',
],
},
{
test: /\.scss$/,
use: [
'vue-style-loader',
'style-loader',
'css-loader',
'sass-loader'
],
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
compilerOptions: {
preserveWhitespace: false
}
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
presets: ['@babel/preset-env'],
}
},
{
test: /\.(png|jpg|gif|svg|jpeg)$/,
loader: 'url-loader',
options: {
limit: 10000,
name: '[name].[ext]?[hash]'
}
},
],
},
performance: {
hints: false
},
plugins: isProd
? [
new VueLoaderPlugin()
]
: [
new VueLoaderPlugin(),
new FriendlyErrorsPlugin()
]
}
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
const { merge } = require('webpack-merge')
const VueSSRClientConfig = merge(baseConfig, {
entry: {
app: './src/entry-client.js'
},
resolve: {
alias: {
'create-api': './create-api-client.js',
},
extensions: ['.js', '.vue']
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
'process.env.VUE_ENV': '"client"'
}),
new VueSSRClientPlugin()
]
})
const nodeExternals = require("webpack-node-externals")
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')
const VueSSRServerConfig = merge(baseConfig, {
target: 'node',
entry: './src/entry-server.js',
output: {
filename: 'server-bundle.js',
path: path.resolve(__dirname, 'dist'),
libraryTarget: 'commonjs2'
},
resolve: {
alias: {
'create-api': './create-api-server.js',
},
extensions: ['.js', '.vue']
},
externals: nodeExternals({
allowlist: /[\.css|\.scss]$/
}),
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
'process.env.VUE_ENV': '"server"'
}),
new VueSSRServerPlugin()
]
})
module.exports = [VueSSRServerConfig, VueSSRClientConfig]
setup-dev-server.js
const fs = require('fs')
const path = require('path')
const MFS = require('memory-fs')
const webpack = require('webpack')
const serverConfig = require('./webpack.config')[0]
const clientConfig = require('./webpack.config')[1]
const readFile = (fs, file) => {
try {
return fs.readFileSync(path.join(clientConfig.output.path, file), 'utf-8')
} catch (e) {}
}
module.exports = function setupDevServer(app, cb) {
let bundle
let clientManifest
let ready
const readyPromise = new Promise(r => { ready = r })
const update = () => {
if (bundle && clientManifest) {
ready()
cb(bundle, { clientManifest })
}
}
// modify client config to work with hot middleware
clientConfig.entry.app = ['webpack-hot-middleware/client', clientConfig.entry.app]
clientConfig.output.filename = '[name].js'
clientConfig.plugins.push(
new webpack.HotModuleReplacementPlugin(),
)
// dev middleware
const clientCompiler = webpack(clientConfig)
const devMiddleware = require('webpack-dev-middleware')(clientCompiler, {
publicPath: clientConfig.output.publicPath,
noInfo: true
})
app.use(devMiddleware)
clientCompiler.hooks.done.tap('done', stats => {
stats = stats.toJson()
stats.errors.forEach(err => console.error(err))
stats.warnings.forEach(err => console.warn(err))
if (stats.errors.length) return
clientManifest = JSON.parse(readFile(
devMiddleware.fileSystem,
'vue-ssr-client-manifest.json'
))
update()
})
// hot middleware
app.use(require('webpack-hot-middleware')(clientCompiler, { heartbeat: 1000 }))
// watch and update server renderer
const serverCompiler = webpack(serverConfig)
const mfs = new MFS()
serverCompiler.outputFileSystem = mfs
serverCompiler.watch({}, (err, stats) => {
if (err) throw err
stats = stats.toJson()
if (stats.errors.length) return
bundle = JSON.parse(readFile(mfs, 'vue-ssr-server-bundle.json'))
update()
})
return readyPromise
}
server.js
const path = require('path')
const express = require('express')
const app = express()
const resolve = file => path.resolve(__dirname, file)
const isProd = process.env.NODE_ENV === 'production'
const { createBundleRenderer } = require('vue-server-renderer')
function createRenderer(bundle, options) {
return createBundleRenderer(bundle, Object.assign(options, {
basedir: resolve('./dist'),
runInNewContext: !isProd,
}))
}
let renderer
let readyPromise
if (isProd) {
const bundle = require('./dist/vue-ssr-server-bundle.json')
const clientManifest = require('./dist/vue-ssr-client-manifest.json')
renderer = createRenderer(bundle, { clientManifest })
} else {
readyPromise = require('./setup-dev-server')(
app,
(bundle, options) => {
renderer = createRenderer(bundle, options)
}
)
}
function render(req, res) {
const context = req.body || {}
const { requestId } = req.body || {}
renderer.renderToString(context, (err, html) => {
// return json
res.json({ requestId, html })
})
}
app.get('/', isProd ? render : (req, res) => {
readyPromise.then(() => render(req, res))
})
app.listen(9991)
答案 0 :(得分:1)
请确保这与您的Webpack配置有关。我认为这是因为样式加载器试图将您的样式注入DOM(服务器端显然不存在)。因此,参考错误。 我不确定100%,但是只能尝试使用vue-style-loader。无需将其与style-loader捆绑在一起,因为它们几乎在做同一件事。
还要在项目上运行build命令,然后查看服务器捆绑包。这将向您显示谁在尝试访问DOM。
编辑:
作为您要执行的操作的一般方法,您还应该在一个规则中包含sass / css,例如:
{
test: /\.(sa|sc|c)ss$/,
use: ['vue-style-loader', 'css-loader', 'sass-loader']
},
答案 1 :(得分:0)
如果您有Sass Pack,则只能更改webpack.config.js:
module: {
loaders: [{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/
}, {
test: /\.vue$/,
loader: 'vue'
}, {
test: /\.s[a|c]ss$/,
loader: 'style!css!sass'
}]
},
vue: {
loaders: {
scss: 'style!css!sass'
}
}
> f未安装的sass包:
npm install -D sass-loader node-sass