Skip to content

Commit

Permalink
Merge pull request #1801 from Automattic/add/webpack-ssr-checker
Browse files Browse the repository at this point in the history
Build: Add pragma check webpack plugin for server side rendering
  • Loading branch information
ehg committed Jan 11, 2016
2 parents f67dc9d + 9a25324 commit 354cd5c
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 1 deletion.
7 changes: 7 additions & 0 deletions server/pragma-checker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
PragmaCheckPlugin
================

This `webpack` plugin scans Calypso source code for the `@ssr-ready` pragma, and reports any dependencies that don't have this pragma.

It is intended to provide immediate runtime feedback to developers modifying components used in Server Side Rendering, where adding a non-compatible dependency may break the server build.

72 changes: 72 additions & 0 deletions server/pragma-checker/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/***** WARNING: ES5 code only here. Not transpiled! *****/

/**
* External dependecies
*/
var error = require( 'chalk' ).bold.red;
var info = require( 'chalk' ).bold.yellow;
var startsWith = require( 'lodash/string/startsWith' );
var includes = require( 'lodash/collection/includes' );

var PLUGIN_TITLE = 'PragmaChecker';
var SSR_READY = '/** @ssr-ready **/';

function PragmaCheckPlugin( options ) {
this.options = options || {};
}

function scanDependencies( module, compilation ) {
if ( ! module.dependencies ) {
return;
}

module.dependencies.forEach( function( dep ) {
if ( ! dep.module ) {
return;
}

// If the module is compiled through babel, we can be pretty sure it's our own module, not from npm.
if ( includes( dep.module.request, 'babel-loader' ) &&
dep.module._source &&
! includes( dep.module._source._value, SSR_READY ) ) {
compilation.errors.push( PLUGIN_TITLE + ': ' + module.rawRequest + ', dependency ' + dep.module.rawRequest + ' is not ' + SSR_READY );
}

if ( dep.module.dependencies ) {
scanDependencies( dep.module.dependencies );
}
} );
}

PragmaCheckPlugin.prototype.apply = function( compiler ) {
compiler.plugin( 'compilation', function( compilation ) {
compilation.plugin( 'optimize-modules', function( modules ) {
modules.forEach( function( module ) {
if ( module._source && includes( module._source._value, SSR_READY ) ) {
scanDependencies( module, compilation );
}
} );
} );

compiler.plugin( 'done', function( stats ) {
var pragmaError = false;

if ( stats.compilation.errors && stats.compilation.errors.length ) {
stats.compilation.errors.forEach( function( text ) {
if ( startsWith( text, PLUGIN_TITLE ) ) {
pragmaError = true;
console.log( error( text ) );
}
} );

if ( pragmaError ) {
console.log( info( PLUGIN_TITLE + ': Server Side Rendering constraints not met. Please see https://github.com/Automattic/wp-calypso/tree/master/shared#shared for details.' ) );
// We don't want to enable webpack's bail for all errors, so exit the process instead of throwing.
process.exit( 1 ); // eslint-disable-line no-process-exit
}
}
} );
} );
};

module.exports = PragmaCheckPlugin;
4 changes: 3 additions & 1 deletion webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ var webpack = require( 'webpack' ),
* Internal dependencies
*/
var config = require( './server/config' ),
ChunkFileNamePlugin = require( './server/bundler/plugin' );
ChunkFileNamePlugin = require( './server/bundler/plugin' ),
PragmaCheckPlugin = require( 'server/pragma-checker' );

/**
* Internal variables
Expand Down Expand Up @@ -96,6 +97,7 @@ jsLoader = {
};

if ( CALYPSO_ENV === 'development' ) {
webpackConfig.plugins.push( new PragmaCheckPlugin() );
webpackConfig.plugins.push( new webpack.HotModuleReplacementPlugin() );
webpackConfig.entry[ 'build-' + CALYPSO_ENV ] = [
'webpack-dev-server/client?/',
Expand Down

0 comments on commit 354cd5c

Please sign in to comment.