我一直在努力使我的vuejs应用程序功能与SSR一致,但我所有的尝试失败。我真的需要帮助。Vuejs 2服务器端渲染 - 不工作
请注意,我使用正常的js文件而不是.vue文件与es6和需要使用webpack require功能的html模板。
的应用工作在发展模式精细,但是,当我开始使用“VUE-服务器渲染”和去任何路线执行它,这个错误将被抛出:
Error: render function or template not defined in component: anonymous at normalizeRender (/Users/salaahassi/dev/vue/magicum/node_modules/vue-server-renderer/build.js:6015:13) at renderComponent (/Users/salaahassi/dev/vue/magicum/node_modules/vue-server-renderer/build.js:6081:3) at renderNode (/Users/salaahassi/dev/vue/magicum/node_modules/vue-server-renderer/build.js:6065:7) at render (/Users/salaahassi/dev/vue/magicum/node_modules/vue-server-renderer/build.js:6257:5) at RenderStream.render (/Users/salaahassi/dev/vue/magicum/node_modules/vue-server-renderer/build.js:6312:9) at RenderStream.tryRender (/Users/salaahassi/dev/vue/magicum/node_modules/vue-server-renderer/build.js:96:12) at RenderStream._read (/Users/salaahassi/dev/vue/magicum/node_modules/vue-server-renderer/build.js:125:12) at RenderStream.Readable.read (_stream_readable.js:348:10) at resume_ (_stream_readable.js:737:12) at _combinedTickCallback (internal/process/next_tick.js:74:11)
此外,当我在浏览器上禁用了JavaScript,甚至主页也会消失(当然这是因为它不适用于SSR)。
这里是我的WebPack:
var path = require('path')
var webpack = require('webpack')
var HTMLPlugin = require('html-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var extractCSS = new ExtractTextPlugin('styles.css');
var options = {
// entry: './entry.client.js',
entry: {
app: './entry.client.js',
vendor: [
'vue',
'vue-router',
'vuex',
'vuex-router-sync',
'moment',
'axios'
]
},
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/',
filename: '[name].[hash].js',
},
module: {
noParse: /es6-promise\.js$/, // avoid webpack shimming process
rules: [
{
test: /\.html$/,
loader: 'raw-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.(png|jpg|gif|svg|woff|woff2|eot|ttf)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
},
{
test: /\.scss$/,
loader: extractCSS.extract('css-loader!sass-loader')
}
]
},
plugins: [
extractCSS,
new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/(en|zh-tw)$/),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify(process.env.NODE_ENV) || 'development',
'VUE_ENV': JSON.stringify(process.env.VUE_ENV) || 'client',
}
})
],
resolve: {
alias: {
'vue$': 'vue/dist/vue'
}
},
devServer: {
historyApiFallback: true,
noInfo: true
},
devtool: '#eval-source-map'
}
console.log("xxxxx ---node env---- xxxx", process.env.NODE_ENV);
console.log("xxxxx ---vue env---- xxxx", process.env.VUE_ENV);
if (process.env.NODE_ENV != 'development') {
options.entry = './entry.server.js';
options.target = 'node';
options.output.filename = 'bundle-server.js';
options.output.libraryTarget = 'commonjs2';
options.externals = Object.keys(require('./package.json').dependencies);
}
if (process.env.NODE_ENV == 'development') {
options.plugins = (options.plugins || []).concat([
new HTMLPlugin({
template: './index.html'
}),
// extract vendor chunks for better caching
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor'
})
]);
}
if (process.env.VUE_ENV == 'server') {
options.devtool = '#source-map'
options.plugins = (options.plugins || []).concat([
new webpack.optimize.UglifyJsPlugin({
//sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
}),
new CopyWebpackPlugin([
{from: './assets', to: 'assets'},
{from: './index.html'}
])
])
}
module.exports = options;
,这里是我的服务器入口文件:
import { app, router, store } from './src/app'
export default context => {
// set router's location
router.push(context.url)
// call prefetch hooks on components matched by the route
const s = Date.now()
return Promise.all(router.getMatchedComponents().map(component => {
if (component.prefetch) {
return component.prefetch(store)
}
})).then(() => {
console.log(`data pre-fetch: ${Date.now() - s}ms`)
// set initial store on context
// the request handler will inline the state in the HTML response.
context.initialState = store.state
return app
})
}
这里是我的server.js:
'use strict'
const fs = require('fs')
const path = require('path')
const resolve = file => path.resolve(__dirname, file)
const express = require('express')
// const favicon = require('serve-favicon')
const serialize = require('serialize-javascript')
const createBundleRenderer = require('vue-server-renderer').createBundleRenderer
const app = express()
// parse index.html template
const template = fs.readFileSync(resolve('./dist/index.html'), 'utf-8')
// create server renderer from real fs
const bundlePath = resolve('./dist/bundle-server.js')
let renderer = createRenderer(fs.readFileSync(bundlePath, 'utf-8'))
console.log(renderer);
function createRenderer (bundle) {
return createBundleRenderer(bundle, {
cache: require('lru-cache')({
max: 1000,
maxAge: 1000 * 60 * 15
})
})
}
var options = {
maxAge: '60d',
setHeaders: function(res, path, stat) {
// Webfonts need to have CORS * set in order to work.
if (path.match(/ttf|woff|woff2|eot|svg/ig)) {
res.set('Access-Control-Allow-Origin', '*');
}
}
};
var dist_path = '/dist/';
app.use(express.static(path.join(__dirname, dist_path), options));
console.log("............");
app.get('*', (req, res) => {
console.log(".....ROUTE.......", req.url);
console.log('renderer', renderer);
if (!renderer) {
return res.end('waiting for compilation... refresh in a moment.')
}
var s = Date.now()
const context = { url: req.url }
const renderStream = renderer.renderToStream(context)
let firstChunk = true
// console.log(html.head);
// res.write(html.head)
renderStream.on('data', chunk => {
if (firstChunk) {
// embed initial store state
if (context.initialState) {
res.write(
`<script>window.__INITIAL_STATE__=${
serialize(context.initialState, { isJSON: true })
}</script>`
)
}
firstChunk = false
}
res.write(chunk)
})
renderStream.on('end',() => {
res.end(template)
console.log(`whole request: ${Date.now() - s}ms`)
})
renderStream.on('error', err => {
throw err
})
})
const port = process.env.PORT || 3000
app.listen(port,() => {
console.log(`server started at http://localhost:${port}`)
})
你尝试从的WebPack的config删除此: ''' 决心:{ 别名:{ 'VUE $': 'VUE /距离/ VUE' } }, ' '' – imcvampire