gpt4 book ai didi

webpack - vue-server-renderer 无法构建包文件

转载 作者:行者123 更新时间:2023-12-03 20:53:07 26 4
gpt4 key购买 nike

我正在尝试创建一个 @vue/cli3 SSR 项目,但似乎无法生成服务器包文件。客户端构建良好。

package.json 脚本

"scripts": {
"serve": "npm run build && node scripts/serve",
"build": "npm run build:server && mv dist/vue-ssr-server-bundle.json bundle && npm run build:client && mv bundle dist/vue-ssr-server-bundle.json",
"build:client": "vue-cli-service build",
"build:server": "cross-env WEBPACK_TARGET=node vue-cli-service build"
}

运行错误 yarn serve
$ yarn serve
yarn run v1.9.2
$ npm run build && node scripts/serve

> project-name@0.1.0 build /path/to/file/project-name
> npm run build:server && mv dist/vue-ssr-server-bundle.json bundle && npm run build:client && mv bundle dist/vue-ssr-server-bundle.json


> project-name@0.1.0 build:server /path/to/file/project-name
> cross-env WEBPACK_TARGET=node vue-cli-service build


⠙ Building for production...(node:24514) DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead
⠏ Building for production...(node:24514) UnhandledPromiseRejectionWarning: Error: Server-side bundle should have one single entry file. Avoid using CommonsChunkPlugin in the server config.
at /path/to/file/project-name/node_modules/vue-server-renderer/server-plugin.js:58:13
at _err2 (eval at create (/path/to/file/project-name/node_modules/tapable/lib/HookCodeFactory.js:24:12), <anonymous>:22:1)
at callback (/path/to/file/project-name/node_modules/copy-webpack-plugin/dist/index.js:77:17)
at /path/to/file/project-name/node_modules/copy-webpack-plugin/dist/index.js:118:24
at <anonymous>
(node:24514) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:24514) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

vue.config.js
const path = require('path')
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
const nodeExternals = require('webpack-node-externals')
const merge = require('lodash.merge')

const TARGET_NODE = process.env.WEBPACK_TARGET === 'node'

const resolve = (file) => path.resolve(__dirname, file)

const target = TARGET_NODE
? 'server'
: 'client'

module.exports = {
configureWebpack: () => ({
entry: {
app: `./src/entry-${target}`
},
target: TARGET_NODE ? 'node' : 'web',
node: TARGET_NODE ? undefined : false,
plugins: [
TARGET_NODE
? new VueSSRServerPlugin()
: new VueSSRClientPlugin()
],
externals: TARGET_NODE ? nodeExternals({
whitelist: /\.css$/
}) : undefined,
output: {
libraryTarget: TARGET_NODE
? 'commonjs2'
: undefined
},
optimization: {
splitChunks: undefined
},
resolve:{
alias: {
'@': resolve('src'),
'public': resolve('public')
}
}
}),
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.tap(options =>
merge(options, {
optimizeSSR: false
})
)
}
}

最后,server.js 文件:
/* eslint-disable no-console */

const fs = require('fs')
const path = require('path')
const express = require('express')
const compression = require('compression')
const favicon = require('serve-favicon')
const microcache = require('route-cache')
const Ouch = require('ouch')
var proxy = require('http-proxy-middleware')
const { createBundleRenderer } = require('vue-server-renderer')

const resolve = file => path.resolve(__dirname, file)

const devServerBaseURL = process.env.DEV_SERVER_BASE_URL || 'http://localhost'
const devServerPort = process.env.DEV_SERVER_PORT || 8080
const isProd = process.env.NODE_ENV === 'production'
const useMicroCache = process.env.MICRO_CACHE !== 'false'

const serverInfo =
`express/${require('express/package.json').version} ` +
`vue-server-renderer/${require('vue-server-renderer/package.json').version}`

const app = express()

function createRenderer (bundle, options) {
return createBundleRenderer(bundle, Object.assign(options, {
runInNewContext: false
}))
}

let renderer
const templatePath = path.resolve(__dirname, './src/index.template.html')

const bundle = require('./dist/vue-ssr-server-bundle.json')
const template = fs.readFileSync(templatePath, 'utf-8')
const clientManifest = require('./dist/vue-ssr-client-manifest.json')
renderer = createRenderer(bundle, {
template,
clientManifest
})

if (process.env.NODE_ENV !== 'production') {
app.use('/js/main*', proxy({
target: `${devServerBaseURL}/${devServerPort}`,
changeOrigin: true,
pathRewrite: function (path) {
return path.includes('main')
? '/main.js'
: path
},
prependPath: false
}))

app.use('/*hot-update*', proxy({
target: `${devServerBaseURL}/${devServerPort}`,
changeOrigin: true
}))

app.use('/sockjs-node', proxy({
target: `${devServerBaseURL}/${devServerPort}`,
changeOrigin: true,
ws: true
}))
}

const serve = (path, cache) => express.static(resolve(path), {
maxAge: cache && isProd ? 1000 * 60 * 60 * 24 * 30 : 0
})

app.use('/js', express.static(path.resolve(__dirname, './dist/js')))
app.use('/css', express.static(path.resolve(__dirname, './dist/css')))
app.use(express.json())
app.use(compression({ threshold: 0 }))
app.use(favicon('./public/favicon.ico'))
app.use('/public/manifest.json', serve('./manifest.json', true))
app.use('/public', serve('./public', true))
app.use('/public/robots.txt', serve('./robots.txt'))

app.get('/sitemap.xml', (req, res) => {
res.setHeader('Content-Type', 'text/xml')
res.sendFile(resolve('./public/sitemap.xml'))
})

// since this app has no user-specific content, every page is micro-cacheable.
// if your app involves user-specific content, you need to implement custom
// logic to determine whether a request is cacheable based on its url and
// headers.
// 10-minute microcache.
// https://www.nginx.com/blog/benefits-of-microcaching-nginx/
const cacheMiddleware = microcache.cacheSeconds(10 * 60, req => useMicroCache && req.originalUrl)

const ouchInstance = (new Ouch()).pushHandler(new Ouch.handlers.PrettyPageHandler('orange', null, 'sublime'))

function render (req, res) {
const start = Date.now()

res.setHeader('Content-Type', 'text/html')
res.setHeader('Server', serverInfo)

const context = {
url: req.url,
res
}

const handleError = err => {
if (err.url) {
res.redirect(err.url)
} else if (err.code === 404) {
res.status(404).send('404 | Page Not Found')
} else {
ouchInstance.handleException(err, req, res, output => {
console.log(JSON.stringify(err))
console.log('Error handled!')
})
}
}

renderer.renderToString(context, (err, html) => {
if (err) return handleError(err)

res.end(html)

!isProd && console.log(`whole request: ${Date.now() - start}ms`)
})
}

app.get('*', render, cacheMiddleware)

const port = process.env.PORT || 8095
const host = process.env.HOST || '0.0.0.0'
app.listen(port, host, () => {
console.log(`server started at ${host}:${port}`)
})

这个错误似乎来自 vue-server-renderer,并且与 https://github.com/vuejs/vue/issues/5553 有某种关系。但它不需要提供有关如何解决此问题的任何线索。所有的 promise 都有 catch 块,所以不应该处理任何拒绝。这仅在 WEBPACK_TARGET === 'node' 时发生因此使用了 VueSSRServerPlugin。

最佳答案

我是这样解决的:

const base = require("@vue/cli-service/webpack.config");
delete base.optimization;

module.exports = merge(base, {
... config related to SSR ...
});

关于webpack - vue-server-renderer 无法构建包文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51688961/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com