美文网首页
解决vue ssr css内联样式和link标签重复问题

解决vue ssr css内联样式和link标签重复问题

作者: redpeanuts | 来源:发表于2020-09-06 14:15 被阅读0次

    基于vue-cli3的项目,改造成SSR。
    服务端渲染会提取组件的样式内联到html中,与link标签中的重复,使得页面体积变大,导致响应时间很慢。
    原因是ssr会自动进行资源注入Manual Asset Injection,包含css、js等。

    我们需要的是没有<style>标签的页面

    所以通过配置参数,关闭资源注入。

    //server.js
    //创建bundlerender
    
    function createRenderer(bundle, options) {
      return createBundleRenderer(
        bundle,
        Object.assign(options, {
          basedir: resolve('./dist'),
          inject: false,
        })
      )
    }
    

    接下来需要把css、js等文件再关联到输出的html中
    当创建bundlerender的时候,我们可以使用一个模板,在这个模板里面预置页面所需要的各种资源。

    //服务端渲染用到的模板
      const templatePath = resolve('./dist/index.ssr.html')
      const template = fs.readFileSync(templatePath, 'utf-8')
      const bundle = require('./dist/vue-ssr-server-bundle.json')
      // The client manifests are optional, but it allows the renderer
      // to automatically infer preload/prefetch links and directly add <script>
      // tags for any async chunks used during render, avoiding waterfall requests.
      const clientManifest = require('./dist/vue-ssr-client-manifest.json')
      renderer = createRenderer(bundle, {
        template,
        clientManifest,
      })
    

    思来想去,csr(客户端渲染)模式下生成的index.html再合适不过了。
    而且,当build csr时,我们也可以预置一个模板,在这里添加上第三方的资源

    --/public
    ----index.html
    

    最后是在模板中添加锚点

    const fs = require('fs')
    
    fs.readFile('./dist/index.html', 'utf8', (err, data) => {
    //替换锚点
      data = data.replace('<div id=app></div>', '<!--vue-ssr-outlet-->')
      fs.writeFile('./dist/index.ssr.html', data, (err) => {
        if (err) throw err
        console.log('The file has been saved!')
      })
    })
    

    到这里基本大功告成

    总结

    • 模板预置页面所需资源
    • 关闭ssr资源自动注入

    贴一下vue.config.js和build script(windows 平台)

    //vue.config.js
    
    const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')
    const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
    const merge = require('lodash.merge')
    const TARGET_NODE = process.env.WEBPACK_TARGET === 'node'
    const target = TARGET_NODE ? 'server' : 'client'
    
    module.exports = {
      configureWebpack: () => ({
        entry: `./src/entry-${target}.js`,
        target: TARGET_NODE ? 'node' : 'web',
        node: TARGET_NODE ? undefined : false,
        output: {
          libraryTarget: TARGET_NODE ? 'commonjs2' : undefined,
        },
        optimization: {
          splitChunks: false,
        },
        plugins: [
          TARGET_NODE ? new VueSSRServerPlugin() : new VueSSRClientPlugin(),
        ],
      }),
      chainWebpack: (config) => {
        config.module
          .rule('vue')
          .use('vue-loader')
          .tap((options) => {
            merge(options, {
              optimizeSSR: false,
            })
          }),
          config.plugin('VuetifyLoaderPlugin').tap((args) => [
            {
              match(originalTag, { kebabTag, camelTag, path, component }) {
                if (kebabTag.startsWith('core-')) {
                  return [
                    camelTag,
                    `import ${camelTag} from '@/components/core/${camelTag.substring(
                      4
                    )}.vue'`,
                  ]
                }
              },
            },
          ])
      },
      transpileDependencies: ['vuetify'],
    }
    
    //build script
    "build:client": "vue-cli-service build",
    "build:server": "cross-env WEBPACK_TARGET=node vue-cli-service build --mode server",
    "build:win": "npm run build:server && move dist\\vue-ssr-server-bundle.json bundle && npm run build:client && move bundle dist\\vue-ssr-server-bundle.json"
    

    相关文章

      网友评论

          本文标题:解决vue ssr css内联样式和link标签重复问题

          本文链接:https://www.haomeiwen.com/subject/mkkcektx.html