vue 服务端渲染开发框架搭建问题

我在使用webpack搭建一个vue服务端渲染的工程,出现了一个问题,我搭建的是多页面开发环境,admin和project两个页面,当我使用webpack打包的时候vue-server-renderer中间件的createRenderer方法返回的html中自动注入了包含admin和project两个页面的js和css,不知道是为什么。麻烦给予帮助,非常感谢。
页面目录:
图片描述

app.js

require("@babel/register")
const Koa = require('koa')
const Router = require('koa-router')
const { routerFile } = require('./server-utils')
const { createRenderer } = require('vue-server-renderer')
const serve = require('koa-static')
const path = require('path')
const isProd = process.env.NODE_ENV === 'production' ? 'production' : 'development'

const app = new Koa()
const router = new Router()

app.use(serve(path.join(__dirname, '/dist')))

if(isProd === 'production'){
  const clientManifest = require('./dist/vue-ssr-client-manifest.json')
  render(clientManifest)
}else{
  const setUpDevServer = require('./build/setup-dev-server')
  setUpDevServer(app, async (clientManifest) => {
    render(clientManifest)
  })
}

function render(clientManifest){
  const entryRouter = routerFile()
  entryRouter.forEach(item => {
    (function(item){
      const server = require(item.appFlile)
      router.get(`/${item.router}`, async ctx => {
        const { app, template } = await server.default(ctx)
        const renderer = createRenderer({
          runInNewContext: false,
          clientManifest,
          template
        })
        const html = await renderer.renderToString(app, {})
        ctx.body = html
      })
    })(item)
  })
}

app.use(router.routes()).use(router.allowedMethods())

app.listen(8080)

server-utils.js

const glob = require('glob')
const path = require('path')

function routerFile(){
  const file = path.resolve(__dirname, `pages/*`)
  const entryObject = glob.sync(file).reduce((entries, entry) => {
    let basename = path.basename(entry)
    const appFlile = `./dist/${basename}-server-bundle.js`
    if(basename.indexOf('.')){
      basename = basename.replace(/\./g, '/')
    }
    entries.push({
      router: basename,
      appFlile
    })
    return entries;
  }, [])
  return entryObject
}

module.exports = {
  routerFile
}

setup-dev-server.js

const webpack = require('webpack')
const koa2Connect = require('koa2-connect');
const webpackDevMiddleware = require("webpack-dev-middleware")
const webpackHotMiddleware = require("webpack-hot-middleware")
const webpackConf = require('./webpack.base.conf')
const webpackClientConf = require('./webpack.client.conf')
const webpackServerConf = require('./webpack.server.conf')
const path = require('path')

const readFile = (fs, file) => {
  try {
    return fs.readFileSync(path.join(webpackConf.output.path, file), 'utf-8')
  } catch (e) {
    console.log("[readFile]", e)
  }
}

module.exports = async function setupDevServer(app, cb){
  const compilerClient = webpack(webpackClientConf)
  const compilerServer = webpack(webpackServerConf)

  const devMiddleware = webpackDevMiddleware(compilerClient, {
    noInfo: true,
    publicPath: webpackConf.output.publicPath,
    stats: {
      colors: true
    }
  })

  app.use(koa2Connect(devMiddleware));
  app.use(koa2Connect(webpackHotMiddleware(compilerClient, {
    log: false,
    noInfo: true,
    quiet: true,
    heartbeat: 10 * 1000
  })));
  
  compilerClient.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
    const clientManifest = JSON.parse(readFile(
      devMiddleware.fileSystem,
      'vue-ssr-client-manifest.json'
    ))
    cb(clientManifest)
  })

  compilerServer.watch({}, (err, stats) => {
    if (err) {
      reject(err)
    }
    stats = stats.toJson()
    stats.errors.forEach(err => console.error(err))
    stats.warnings.forEach(err => console.warn(err))
  })
}

webpack.client.conf.js

const webpack = require('webpack');
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
const { getEntryPoint } = require('./entry')
const entryObj = getEntryPoint('index')
let entry = null

if(baseWebpackConfig.mode === 'production'){
  entry = entryObj
}else{
  entry = Object.keys(entryObj).reduce((obj, cur) => {
    const hmr = `webpack-hot-middleware/client?name=${cur}&reload=true&timeout=20000`;
    obj[cur] = []
    obj[cur].push(entryObj[cur], hmr)
    return obj
  }, {})
  // 小记:hmr文件 必须和入口文件放在一起哦!
}
console.log("entry::::::::::::", entry)
const clientConf = merge(baseWebpackConfig, {
  entry,
  optimization: {
    splitChunks: {
      chunks: 'all',
      minChunks: 2,
      name: 'manifest'
    }
  },
  devtool: 'source-map',
  plugins: [
    new VueSSRClientPlugin(),
    new webpack.HotModuleReplacementPlugin()
  ]
})

module.exports = clientConf

webpack.server.conf.js

const path = require('path')
const merge = require('webpack-merge')
const nodeExternals = require('webpack-node-externals')
const baseConfig = require('./webpack.base.conf.js')
const { getEntryPoint } = require('./entry')
const entry = getEntryPoint('index.server')

const serverConf = merge(baseConfig, {
  entry,
  target: 'node',
  output: {
    path: path.join(__dirname, '../dist'),
    filename: '[name]-server-bundle.js',
    libraryTarget: 'commonjs2'
  },
  externals: nodeExternals({ // 不打包node_modules依赖项 whitelist 白名单
    whitelist: /\.css$/
  })
})

module.exports = serverConf

entry.js

const glob = require('glob')
const path = require('path')

const getEntryPoint = function(fileName){
  const file = path.resolve(__dirname, `../pages/*`)
  const entryObject = glob.sync(file).reduce((entries, entry) => {
    const basename = path.basename(entry)
    entries[basename] = `${entry}/${fileName}.js`
    return entries;
  }, {})
  return entryObject
}
module.exports = {
  getEntryPoint
}

最后我启动服务以后 通过http://localhost:8080/project访问project页面,给我返回的HTML是这样的 包含了admin的js和css
图片描述

求大神给予帮助。非常非常非常感谢。

阅读 1.3k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题