vue预渲染 render-spa-plugin

vue预渲染 render-spa-plugin

  1. 全局安装

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

    ? Generate project in current directory? Yes
    ? Project name prerender-spa
    ? Project description A Vue.js project
    ? Author dxc1996 <18895364886@163.com>
    ? 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. 安装插件

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

    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下配置

    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',
          })
        })
    ]
    

    整体来说是这样的

    '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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值