chrisvfritz / prerender-spa-plugin

Prerenders static HTML in a single-page application.
MIT License
7.31k stars 633 forks source link

Webpack not building 100% when renderAfterDocumentEvent is defined #269

Open alexis-regnaud opened 5 years ago

alexis-regnaud commented 5 years ago

Hey,

I Use VueJs + webpack encore (Symfony 3). I would use the prerender-spa-plugin but when I defined a renderAfterDocumentEvent option, my npm run dev building is blocked at 95% emitting.

image

If I remove the renderAfterDocumentEvent option, the running has 100% but pages html are empty :

index.html : image

This is my webpackconfig.js :

// webpack.config.js
const Encore = require('@symfony/webpack-encore');
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const PrerenderSpaPlugin = require('prerender-spa-plugin');
const Renderer = PrerenderSpaPlugin.PuppeteerRenderer
//const JSDOMRenderer = require('@prerenderer/renderer-jsdom')

Encore
// the project directory where all compiled assets will be stored
    .setOutputPath('web/build/')
    // the public path used by the web server to access the previous directory
    .setPublicPath('/')

    /**Loader**/
    .addLoader({ test: /\.js$/, loader: 'babel-loader?cacheDirectory', include: [/node_modules\/foundation-sites/]})
    .addLoader({ test: /\.js$/, loader: 'babel-loader?cacheDirectory', include: [/node_modules\/vuex-cache/]})
    .addLoader({
        test: /\.js$/,
        enforce: 'pre',
        loader: 'eslint-loader',
        exclude: /node_modules/,
        options: {
            fix: true,
            emitWarning: true
       }
   })
    .addLoader({
        test: /\.modernizrrc\.js$/,
        loader: 'webpack-modernizr-loader',
        exclude: /node_modules/,
    })
    /** Add entry **/
    // will create public/build/app.js and public/build/app.css
    .addEntry('polyfill', ["babel-polyfill"])
    .addEntry('entrypoint', './assets/vue/entrypoint.js')
    //Style
    .addStyleEntry('app_style',[
        './assets/scss/app.scss'
    ])
    /***************/

    // allow legacy applications to use $/jQuery as a global variable
    .autoProvidejQuery()

    // enable source maps during development
    .enableSourceMaps(!Encore.isProduction())

    // empty the outputPath dir before each build
    .cleanupOutputBeforeBuild()

    // create hashed filenames (e.g. app.abc123.css)
    .enableVersioning(Encore.isProduction())

    // allow sass/scss files to be processed
    .enableSassLoader(function(sassOptions) {}, {
        resolveUrlLoader: false
    })

    // to enable vue
    .enableVueLoader()
    .enablePostCssLoader((options) => {
        options.config = {
            path: './postcss.config.js'
        };
    })

    /** Add plugin **/
    .addPlugin(
        new HtmlWebpackPlugin({
            title: 'PRODUCTION prerender-spa-plugin',
            template: path.resolve(__dirname, './app/Resources/views/front/other.html'),
            filename: path.resolve(__dirname, './web/build/index.html')
        })
    )
    .addPlugin(
        new PrerenderSpaPlugin({
            staticDir: path.join(__dirname, 'web/build'),
            routes: [ '/', '/about', '/contact' ],
            renderer: new Renderer({
                inject: {
                    foo: 'bar'
                },
               /* headless: false, */ 
                renderAfterDocumentEvent: 'render-event'
            }),
            renderAfterElementExists: '#app-vue'
        })
    )
/***************/
;

let config = Encore.getWebpackConfig();

if(Encore.isProduction()){
    /*** Uglify accept ES6 ****/
    // Remove the old version first
    config.plugins = config.plugins.filter(
        plugin => !(plugin instanceof webpack.optimize.UglifyJsPlugin)
    );
    // Add the new one
    config.plugins.push(new UglifyJsPlugin({
        cache: true,
        parallel: true
    }));
    /*********************/
}
/* global __dirname */
config.resolve.alias = {
    assets: path.resolve(__dirname, './web/assets'),
    modernizr$: path.resolve(__dirname, "./.modernizrrc.js"),
    vue$: 'vue/dist/vue.esm.js'
};
module.exports = config;
alexis-regnaud commented 5 years ago

After testing, the blocked statu is only in dev build, in a prod build 100% are emitting.. In my proccess will not be a blocking problem because the prerender will be only in prod build.

But I have always a issu, my compiled assets are in a build folder (.js and .css) but actualy in the index.html the link is : <script type="text/javascript" src="/entrypoint.1429cc83.js"></script> Instead of : <script type="text/javascript" src="/build/entrypoint.1429cc83.js"></script>

I tried to change .setPublicPath('/') in .setPublicPath('/build') or .setPublicPath('/build/') but the building again blocked to 95% ..

light0x00 commented 4 years ago

I have the same problem that I was build the official example, which is always blocked and shows "98% after emitting PrerenderSPAPlugin". When I removed the renderAfterDocumentEvent, it worked.

ajayidavid99 commented 4 years ago

It stays at 98% cos PrerenderSPAPlugin is waiting for DocumentEvent to fire but it's not firing. It will actually keep waiting forever, so try figure out why DocumentEvent is not firing and you have your way!

luoshenxia commented 3 years ago

you should move document.dispatchEvent(new Event('render-event')) to root. like this: let app = new Vue({ el: '#app', router, render: h => h(App), mounted() { // You'll need this for renderAfterDocumentEvent. setTimeout(() => { document.dispatchEvent(new Event('render-event')); }, 5000); }, });