vue预渲染 render-spa-plugin

vue预渲染 render-spa-plugin

  1. 全局安装

    1
    npm install -g @vue/cli-init
  2. 创建vebpack项目
    vue init webpack . // 在当前文件夹下创建项目

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ? Generate project in current directory? Yes
    ? Project name prerender-spa
    ? Project description A Vue.js project
    ? Author dxc1996 <[email protected]>
    ? Vue build standalone
    ? Install vue-router? Yes
    ? Use ESLint to lint your code? No
    ? Set up unit tests No
    ? Setup e2e tests with Nightwatch? No
    ? Should we run `npm install` for you after the project has been created? (recommended) npm

  3. 安装插件

    1
    npm/cnpm i prerender-spa-plugin -D
  4. 路由模式要为history

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import Vue from 'vue'
    import Router from 'vue-router'
    import Home from '@/components/Home'
    import About from '@/components/About'
    import Test from '@/components/Test'

    Vue.use(Router)

    export default new Router({<!-- -->
      mode:'history',
      routes: [
        {<!-- -->path: '/',name: 'Home',component: Home},
        {<!-- -->path: '/about',name: 'About',component: About},
        {<!-- -->path: '/test',name: 'Test',component: Test}
      ]
    })

    这是我的目录结构
    在这里插入图片描述

  5. 在webpack.prod.config.js下配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    const PrerenderSPAPlugin = require('prerender-spa-plugin');
    // 调用渲染器
    const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
    plugins:[
          ...
    //调用渲染器
        new PrerenderSPAPlugin({<!-- -->
          staticDir: path.join(__dirname, '../dist'),
          // Required - Routes to render.
          routes: [ '/', '/about'],
          renderer: new Renderer({<!-- -->
            inject: {<!-- -->
              foo: 'bar'
            },
            headless: false,
            // 在项目的入口使用document.dispatchEvent(new Event('render-event'))
            renderAfterDocumentEvent: 'render-event',
          })
        })
    ]

    整体来说是这样的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    'use strict'
    const path = require('path')
    const utils = require('./utils')
    const webpack = require('webpack')
    const config = require('../config')
    const merge = require('webpack-merge')
    const baseWebpackConfig = require('./webpack.base.conf')
    const CopyWebpackPlugin = require('copy-webpack-plugin')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const ExtractTextPlugin = require('extract-text-webpack-plugin')
    const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
    const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
    const PrerenderSPAPlugin = require('prerender-spa-plugin');
    // 调用渲染器
    const Renderer = PrerenderSPAPlugin.PuppeteerRenderer

    const env = require('../config/prod.env')

    const webpackConfig = merge(baseWebpackConfig, {<!-- -->
      module: {<!-- -->
        rules: utils.styleLoaders({<!-- -->
          sourceMap: config.build.productionSourceMap,
          extract: true,
          usePostCSS: true
        })
      },
      devtool: config.build.productionSourceMap ? config.build.devtool : false,
      output: {<!-- -->
        path: config.build.assetsRoot,
        filename: utils.assetsPath('js/[name].[chunkhash].js'),
        chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
      },
      plugins: [
        // http://vuejs.github.io/vue-loader/en/workflow/production.html
        new webpack.DefinePlugin({<!-- -->
          'process.env': env
        }),
        new UglifyJsPlugin({<!-- -->
          uglifyOptions: {<!-- -->
            compress: {<!-- -->
              warnings: false
            }
          },
          sourceMap: config.build.productionSourceMap,
          parallel: true
        }),
        // extract css into its own file
        new ExtractTextPlugin({<!-- -->
          filename: utils.assetsPath('css/[name].[contenthash].css'),
          // Setting the following option to `false` will not extract CSS from codesplit chunks.
          // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
          // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
          // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
          allChunks: true,
        }),
        // Compress extracted CSS. We are using this plugin so that possible
        // duplicated CSS from different components can be deduped.
        new OptimizeCSSPlugin({<!-- -->
          cssProcessorOptions: config.build.productionSourceMap
            ? {<!-- --> safe: true, map: {<!-- --> inline: false } }
            : {<!-- --> safe: true }
        }),
        // generate dist index.html with correct asset hash for caching.
        // you can customize output by editing /index.html
        // see https://github.com/ampedandwired/html-webpack-plugin
        new HtmlWebpackPlugin({<!-- -->
          filename: config.build.index,
          template: 'index.html',
          inject: true,
          minify: {<!-- -->
            removeComments: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true
            // more options:
            // https://github.com/kangax/html-minifier#options-quick-reference
          },
          // necessary to consistently work with multiple chunks via CommonsChunkPlugin
          chunksSortMode: 'dependency'
        }),
        // keep module.id stable when vendor modules does not change
        new webpack.HashedModuleIdsPlugin(),
        // enable scope hoisting
        new webpack.optimize.ModuleConcatenationPlugin(),
        // split vendor js into its own file
        new webpack.optimize.CommonsChunkPlugin({<!-- -->
          name: 'vendor',
          minChunks (module) {<!-- -->
            // any required modules inside node_modules are extracted to vendor
            return (
              module.resource &&
              /\.js$/.test(module.resource) &&
              module.resource.indexOf(
                path.join(__dirname, '../node_modules')
              ) === 0
            )
          }
        }),
        // extract webpack runtime and module manifest to its own file in order to
        // prevent vendor hash from being updated whenever app bundle is updated
        new webpack.optimize.CommonsChunkPlugin({<!-- -->
          name: 'manifest',
          minChunks: Infinity
        }),
        // This instance extracts shared chunks from code splitted chunks and bundles them
        // in a separate chunk, similar to the vendor chunk
        // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
        new webpack.optimize.CommonsChunkPlugin({<!-- -->
          name: 'app',
          async: 'vendor-async',
          children: true,
          minChunks: 3
        }),

        // copy custom static assets
        new CopyWebpackPlugin([
          {<!-- -->
            from: path.resolve(__dirname, '../static'),
            to: config.build.assetsSubDirectory,
            ignore: ['.*']
          }
        ]),
        //调用渲染器
        new PrerenderSPAPlugin({<!-- -->
          // Required - The path to the webpack-outputted app to prerender.
          staticDir: path.join(__dirname, '../dist'),
          // Required - Routes to render.
          routes: [ '/', '/about'],

          renderer: new Renderer({<!-- -->
            // Optional - Any values you'd like your app to have access to via `window.injectProperty`.
            inject: {<!-- -->
              foo: 'bar'
            },
            // Other puppeteer options.
            // (See here: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions)
            headless: false, // Display the browser window when rendering. Useful for debugging.
     
            // Optional - Wait to render until the specified event is dispatched on the document.
            // eg, with `document.dispatchEvent(new Event('custom-render-trigger'))`
            // 在项目的入口使用document.dispatchEvent(new Event('render-event'))
            renderAfterDocumentEvent: 'render-event',
     
          })
        })
      ]
    })

    if (config.build.productionGzip) {<!-- -->
      const CompressionWebpackPlugin = require('compression-webpack-plugin')

      webpackConfig.plugins.push(
        new CompressionWebpackPlugin({<!-- -->
          asset: '[path].gz[query]',
          algorithm: 'gzip',
          test: new RegExp(
            '\\.(' +
            config.build.productionGzipExtensions.join('|') +
            ')$'
          ),
          threshold: 10240,
          minRatio: 0.8
        })
      )
    }

    if (config.build.bundleAnalyzerReport) {<!-- -->
      const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
      webpackConfig.plugins.push(new BundleAnalyzerPlugin())
    }

    module.exports = webpackConfig
  6. 配置main.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    new Vue({<!-- -->
      el: '#app',
      router,
      components: {<!-- --> App },
      template: '<App/>',
      mounted(){<!-- -->
        document.dispatchEvent(new Event('render-event'))
      }
    })
  7. 打包后的文件
    在这里插入图片描述
    在这里插入图片描述
    如有雷同,请联系删除