Code Monkey home page Code Monkey logo

universal-webpack's Issues

Resolving css node_modules

I typically use normalize.css to reset styles in my apps, in the client config I can just add require('normalize.css') which runs fine, however in the server configuration it does not get parsed as it's seen as an external module which can just be "required", however this breaks the build. I've created a repo to illustrate the issue here: https://github.com/LukeSheard/universal-webpack-bug.

You'll see in server.js that we simply just have a require('normalize.css') statement still in the code, but this obviously fails when you run the build with

$PATH_TO_PROJECT/node_modules/normalize.css/normalize.css:13
html {
     ^
SyntaxError: Unexpected token { ...

Running into issues with modules not resolving on server script

Errors are as follows:

Module not found: Error: Cannot resolve module 'webpack/hot/dev-server' in /opt
resolve module webpack/hot/dev-server in /opt
  looking for modules in /node_modules
    /node_modules/webpack doesn't exist (module as directory)
[/node_modules/webpack]
 @ multi app
multi vendor
Module not found: Error: Cannot resolve module 'webpack/hot/dev-server' in /opt
resolve module webpack/hot/dev-server in /opt
  looking for modules in /node_modules
    /node_modules/webpack doesn't exist (module as directory)
[/node_modules/webpack]
 @ multi vendor
multi vendor
Module not found: Error: Cannot resolve module 'react' in /opt...

And

ERROR in Entry module not found: Error: Cannot resolve directory './app/server' in /opt
resolve directory ./app/server in /opt
  /opt/app/server/package.json doesn't exist (directory description file)
  /opt/app/server doesn't exist (directory default file)

It seems like the issues are coming from the requires in my app. In the repo description you mentioned that this project doesn't hack server side requires, so does that mean that these issues should be best solved with the isomorphic tools version?

Thanks in advance!

Help with favicon

I'm having some trouble getting a favicon to populate correctly in the client bundle.

It's required as follows:

const favicon = require('../images/favicon.png')

But the file gets bundled in the server folder of my build directory, and not the /assets folder.

Build structure:

dist/
|__server/
|__assets/

Also my webpack config uses:

// ...
output: {
    path: PATHS.build, // path.join(__dirname, 'dist/assets')
    publicPath: '/assets/',
    filename: "bundle_[hash].js",
    sourceMapFilename: "bundle_[hash].js.map"
  },

universal-webpack setup for current webpack project, need help

Thanks for this project.

I'm trying to follow the readme and have almost the same settings, but I'm having the following error when I run babel-node "./src/server/startServer"

TypeError: Cannot read property 'path' of undefined
at chunk_info_file_path (/Users/roy/development/projects/react-redux-boilerplate/node_modules/universal-webpack/source/chunks.js:5:19)
at /Users/roy/development/projects/react-redux-boilerplate/node_modules/universal-webpack/source/server.js:22:37

And also, I don't know if I'm setting up correctly ( the webpack.config.client.js and webpack.config.server.js seems okay, at least not throwing error )

Here is my start server

import { server } from 'universal-webpack'
import settings from '../../universal-webpack-settings'
// `configuration.context` and `configuration.output.path` are used
import configuration from '../../webpack.config.babel'

// somehow I need this or it will throw error that my config has no context
configuration.context = configuration.default.context

server(configuration, settings)

Thanks for helping, I wonder if there is any gitter or chat channel to talk about problems ?

More detailed example for separating a react rendering service from the main code

I can't grasp how to separate those things and the docs are a bit confusing. My initial understanding was to have a nodemon server for monitoring a server rendering and then have another node server with a proxy configured to serve requests from the nodemon server. But I can't understand how this would help with making things more faster, because there is still a node server with nodemon to watch the files.

Can you provide a more detailed example on how to do this or maybe a more detailed explanation for how things should work?

More instructions about exclude_from_externals

Hi @halt-hammerzeit,

Thanks for this awesome lib first.

I ran into a problem when my app requires some css file from a library in node_modules, it has taken me quite some time to figure out exclude_from_externals can deal with this

(I had to look in to server configuration.js's source code, seen your comments there)

From the docs I read, I can understand its about webpack, people shall learn this setting from webpack docs, but still a little more instructions can make people aren't webpack experts like me 's life easier

maybe something like:

When requiring non-js files from node_modules, you must mark them as non-external so webpack buildings for server side can process them

webpack-chunks.json configurable request

I have two entrys in my webpack file and start it separately, but webpack-chunks.json always be covered,so at 'universal.settings.js':

module.exports = {
  server: {input: 'xxx', output: 'xxx'}
  chunkFilename: 'xxxx-webpack-chunk.json' 
}

please support it #43

Define enviroment variable whether if it's a server or client build

With webpacks DefinePlugin

There are serveral use cases this can be helpful to include some piece of code from the shared libararies only in a specific build.

It could be named "TARGET" = "client" || "server"

In the code then you can use for example:

if (process.env.TARGET == 'server') {
    apiBaseURL = '127.0.0.1:80'
    ...handleCookie passing...
}

etc.

This don't exposes server side code to the user.

__dirname is / in server modules

Hey, thanks for this module, trying to get css modules and webpack working with some server side rendered react components at the moment.

I set it up just like the instructions in the readme and now my express code can't find the jade views as __dirname is now '/'

my express code looks something like:

app.set('views', __dirname + 'views')

// ... other stuff

res.status(200).render('index.ejs', {reactOutput, initialState})

which of course now fails because my views directory can't be found.

What have I done wrong? :)

update to 0.1.20 error running the production script

I upgraded to 0.1.20 to use the stylesheet optional paramenters.

Now when I run in production (that it was perfectly working before), I have this error:

          | /usr/src/app/webpack/webpack.config.client.production.js:105
          | scss_loader.loader = _extractTextWebpackPlugin2.default.extract(scss_loader.loaders.shift(), scss_loader.loaders.join('!'));
          |                                                                                    ^
          | 
          | TypeError: Cannot read property 'shift' of undefined
          |     at Object.<anonymous> (webpack.config.client.production.js:83:50)
          |     at Module._compile (module.js:409:26)
          |     at loader (/usr/src/app/node_modules/babel-register/lib/node.js:158:5)
          |     at Object.require.extensions.(anonymous function) [as .js] (/usr/src/app/node_modules/babel-register/lib/node.js:168:7)
          |     at Module.load (module.js:343:32)
          |     at Function.Module._load (module.js:300:12)
          |     at Module.require (module.js:353:17)
          |     at require (internal/module.js:12:17)
          |     at Object.<anonymous> (/usr/src/app/webpack/webpack.config.client.production.entry.js:3:18)
          |     at Module._compile (module.js:409:26)
          |     at Object.Module._extensions..js (module.js:416:10)
          |     at Module.load (module.js:343:32)
          |     at Function.Module._load (module.js:300:12)
          |     at Module.require (module.js:353:17)
          |     at require (internal/module.js:12:17)
          |     at module.exports (/usr/src/app/node_modules/webpack/bin/convert-argv.js:80:13)
          | 
          | npm info react-frost@ Failed to exec production-build-client script
          | npm ERR! Linux 4.4.0-31-generic
          | npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "run-script" "production-build-client"
          | npm ERR! node v4.4.7
          | npm ERR! npm  v2.15.8
          | npm ERR! code ELIFECYCLE
          | npm ERR! react-frost@ production-build-client: `webpack --colors --display-error-details --config ./webpack/webpack.config.client.production.entry.js`
          | npm ERR! Exit status 1
          | npm ERR! 
          | npm ERR! Failed at the react-frost@ production-build-client script 'webpack --colors --display-error-details --config ./webpack/webpack.config.client.production.entry.js'.
          | npm ERR! This is most likely a problem with the react-frost package,
          | npm ERR! not with npm itself.
          | npm ERR! Tell the author that this fails on your system:
          | npm ERR!     webpack --colors --display-error-details --config ./webpack/webpack.config.client.production.entry.js
          | npm ERR! You can get information on how to open an issue for this project with:
          | npm ERR!     npm bugs react-frost
          | npm ERR! Or if that isn't available, you can get their info via:
          | npm ERR! 
          | npm ERR!     npm owner ls react-frost
          | npm ERR! There is likely additional logging output above.
          | 
          | npm ERR! Please include the following file with any support request:
          | npm ERR!     /usr/src/app/npm-debug.log
          | ERROR: "production-build-client" exited with 1.
          | 
          | npm info react-frost@ Failed to exec production script
          | npm ERR! Linux 4.4.0-31-generic
          | npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "production"
          | npm ERR! node v4.4.7
          | npm ERR! npm  v2.15.8
          | npm ERR! code ELIFECYCLE
          | npm ERR! react-frost@ production: `npm-run-all production-build-client production-build-server production-server`
          | npm ERR! Exit status 1
          | npm ERR! 
          | npm ERR! Failed at the react-frost@ production script 'npm-run-all production-build-client production-build-server production-server'.
          | npm ERR! This is most likely a problem with the react-frost package,
          | npm ERR! not with npm itself.
          | npm ERR! Tell the author that this fails on your system:
          | npm ERR!     npm-run-all production-build-client production-build-server production-server
          | npm ERR! You can get information on how to open an issue for this project with:
          | npm ERR!     npm bugs react-frost
          | npm ERR! Or if that isn't available, you can get their info via:
          | npm ERR! 
          | npm ERR!     npm owner ls react-frost
          | npm ERR! There is likely additional logging output above.
          | 
          | npm ERR! Please include the following file with any support request:
          | npm ERR!     /usr/src/app/npm-debug.log

it seems that the loaders property undefined.

Do you think that it is connected to your last modifications?

Webpack loaders do not work when using `require`/`import` in nested components

I have a react app which uses react-router and babel. I use code splitting in my router.
Each route is assigned to some component which then includes other components and assets (.scss, .png).

When I include just components without any assets all works perfect.
When I include assets (e.g. logo.png) directly on a code-split component (e.g. Home.js) it works perfect, too.

However, the problem appears when I include assets in a component that is used by Home.js, e.g. Navigation.js includes logo.png.

Is this a bug, or is it not supported?
Could you guide me where in the code loaders are applied to require/import? Perhaps I could do a fork.

Remove webpack dependency on production

This isn't really an issue, since it really solvable without any changes in the code, but I'll explain. I want to remove the dependency of webpack in the production build, since i deploy the built bundle already.

My problem is that universal-webpack forces me to put webpack in my (non dev-)dependencies:

import { server_configuration } from 'universal-webpack'
import settings from './universal-webpack-settings'
import configuration from './webpack.config' // THIS requires webpack and another things which should belong only to dev: postcss plugins etc...

export default server_configuration(configuration, settings)

I've looked into the server.js file and it seems it only requires the context and the output paths, so it is possible to pass just those paths and be done with it, requiring the entire webpack config is a bit unnecessary.

So like I said, it really isn't an issue since we can just change it to:

import { server_configuration } from 'universal-webpack'
import settings from './universal-webpack-settings'

export default server_configuration({
  context: /* context path */,
  output: {
    path: /* server build output */
  }
}, settings)

But maybe document it?

Webpack-chunks written to root dir

I followed the instructions from the readme and I get this error:
Unhandled rejection Error: EACCES: permission denied, open '/webpack-chunks.json'

I am running webpack-dev-server --config webpack.client.config.js. It turns out that webpack_config.output.path get overwritten to /.

webpack.client.config.js:

const clientConfig = client_configuration(configuration, settings);
console.log('client config', clientConfig.output.path);

export default clientConfig;

chunk.js

function chunk_info_file_path(webpack_configuration) {
  console.log('chunk location', webpack_configuration.output.path)

output:

client config /home/myproject/dist/public
chunk location /

When I run webpack --config webpack.client.config.js I have no issue.

readme.md commands do not work

In all of your command examples i.e.
webpack-dev-server --hot --inline --config "./webpack.config.client.js" --port XXXX --colors --display-error-details

you should postpone babel-node otherwise node.js does not support import ES6 stuff. Unless i am missing something ?

Using ReduxAsyncConnect with universal-webpack

I'm porting my code over from using webpack-isomorphic-tools to universal-webpack. I based my project off of https://github.com/erikras/react-redux-universal-hot-example . As far as I can tell, ReduxAsyncConnect expects certain properties to be passed to it from react-router's match (https://www.npmjs.com/package/redux-async-connect), but I'm not sure how to get access to those properties from within my react-isomorphic-render file.

Is there any way to get access to those properties?

Provide a webpack 2 example

Hi.
I have been using universal-webpack for a while and recently became curious in migrating my project to webpack 2. However, even though in one of the closed issues you mention that universal-webpack should be working with webpack 2 - it doesn't, since passing one raw configuration through webpack 2 works and trying to wrap it in the client_configuration - throws an error "TypeError: undefined is not iterable!".

I couldn't find a source of that error in the configuration though, but I think that it would be really useful if you could try to migrate this project to webpack 2.

Thanks.

modules config in webpack 2

I have a webpack config with the following:

resolve: {
    modules: ['app', 'node_modules'],
}

But it seems to not work with universal-webpack. I've tried using alias, but it still doesn't work.

Upon following the instructions and running "webpack --watch --config "./webpack.config.server.js" --colors --display-error-details" I receive error "Unexpected token import"

It is complaining about the first line in

(function (exports, require, module, __filename, __dirname) { import { clientConfiguration } from 'universal-webpack'

Now I know node doesn't support es6 imports and I've used babel-import in my project but it doesn't get a chance to load once I've integrated universal-webpack. I've followed the instructions to a tea and it doesn't mention anything about babel so I'm curious, is something missing from the instructions or am I doing something wrong?

Is there a way to make webpack's resolve work both on client and server?

In my app, the main folder is src, and when I want to import a component, I would like to write
import {Test} from 'components', rather than import {Test} from '../../components'.

The webpack's resolve.moduleDirectories along with NODE_PATH env works, but only for the client build, whereas when I am trying to start the server, it throws an Unexpected token error when trying to import anything but js (styles, images, etc..).

Using relative paths is not that crucial for me, but if there is a chance to set up my project with the resolve rule, I would like to do so.
Thanks.

Errors during server startup don't get printed

My server was throwing an error at startup due to an environment variable that was missing. When I started the server using universal-webpack this error was not shown whatsoever. This results in the server stopping on start without any output in the console.

I don't have time to do a proper PR, so for now I'll submit this issue.

Production question

Hello @halt-hammerzeit,

Thanks for universal-webpack, it's been working great for me in development.

For production usage, it seems that you're running your server through import {server} from 'universal-webpack', same as in dev.

In my case, I'd like to avoid if possible running my production server through an extra layer, if possible.

The solution I'm using at the moment is a start-prod-server.js script. It does the following:

var server = require('./build/server/server').default;
var chunks = require('./build/assets/webpack-chunks.json');
server({chunks: () => chunks});

It seems to be working well at the moment. Do you see anything wrong with this?

import token from .scss file illegal

I keep running into this error. This is my start-server.js file.

const { server } = require('universal-webpack');
const settings = require('./config/universal-webpack-settings');
const serverConfig = require('./config/webpack.config.server');

server(serverConfig, settings);

This is my settings file:

const { DIST, SRC } = require('./paths');
const path = require('path');

module.exports = {
  server:
  {
    input: path.join(SRC, 'server-entry.js'),
    output: path.join(DIST, 'server.js')
  }
};

This is my server-entry.js file. If i comment out the require('./server/server.js'), and the setupServer() part, it will work flawlessly, but I need that setupServer part.

require('babel-polyfill');
import express from 'express';
import SwaggerExpress from 'swagger-express-mw';

import {SWAGGER} from './config/paths';
import './config/environment';

function startServer (parameters) {
  const app = express();

  var config = {
    appRoot: SWAGGER
  };
  SwaggerExpress.create(config, (err, swaggerExpress) => {
    if (err) {
      throw err;
    }
    const setupServer = require('./server/server');
    // This installs the middleware
    swaggerExpress.register(app);
    setupServer(app);

    app.listen(process.env.PORT, () => {
      console.log(`listening at http://localhost:${process.env.PORT}`); // eslint-disable-line
    });

  });
}

module.exports = startServer;

Here is my setupSever.js file

import React from 'react';
import { renderToString } from 'react-dom/server';
import express from 'express';
import debug from 'debug';
import morgan from 'morgan';

import compression from 'compression';
import Error500 from './templates/Error500';
import { routingApp, setRoutes } from './router';
import initFirebase from './api/firebase';

const setUpServer = (server, assets) => {
  const log = debug('preact-lego.js, setting up server.js');
  log('starting');
  initFirebase();

  server.set('etag', true);
  server.use((req, res, next) => {
    res.header('Cache-Control', 'no-cache, no-store, must-revalidate');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
    res.header('Pragma', 'no-cache');
    res.header('Expires', 0);
    next();
  });
  server.use(morgan('combined'));
  server.use(compression());
  server.enable('view cache');
  server.enable('strict routing');

  Object.assign(express.response, {
    renderPageToString(page) {
      return `<!doctype html>${renderToString(page)}`;
    },
    render500(e) {
      console.log(" This is a 500 error", e);
      log('render500', e);
      this.status(500).send(this.renderPageToString(<Error500 />));
    }
  });
  server.use('/', routingApp);

  setRoutes(assets);
};
export default setUpServer;
/node_modules/react-toolbox/lib/ripple/theme.scss:1
(function (exports, require, module, __filename, __dirname) { @import "../colors";
                                                                                                 ^
SyntaxError: Unexpected token ILLEGAL
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:511:25)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:456:32)
    at tryModuleLoad (module.js:415:12)
    at Function.Module._load (module.js:407:3)
    at Module.require (module.js:466:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (.........../node_modules/react-toolbox/lib/ripple/index.js:13:14)
    at Module._compile (module.js:541:32)
SyntaxError: Unexpected token ILLEGAL
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:511:25)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:456:32)
    at tryModuleLoad (module.js:415:12)
    at Function.Module._load (module.js:407:3)
    at Module.require (module.js:466:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (...../node_modules/react-toolbox/lib/ripple/index.js:13:14)
    at Module._compile (module.js:541:32)

Also, this is my package.json file and I'm currently running npm run start:dev:

 "build:dev": "NODE_CONFIG_DIR=src/config NODE_ENV=development webpack-dev-server --hot --inline --config src/config/webpack.config.dev.js --port 3001",
    "build:server": "NODE_CONFIG_DIR=src/config webpack --config src/config/webpack.config.server.js",
    "start": "NODE_CONFIG_DIR=src/config NODE_ENV=production node compiled/server.js",
    "start:dev": "NODE_CONFIG_DIR=src/config npm-run-all --parallel build:dev build:server development-server",
    "development-server": "NODE_CONFIG_DIR=src/config nodemon src/start-server.js --watch compiled/dist --ignore src/app --exec babel-node",
    "prep-server": "universal-webpack --settings src/config/universal-webpack-settings.js",

Can you help me figure out what is going on?

Optional jsdom

Lot of projects use the window object to add events etc. to the DOM. When we have an option in the universal settings like "jsdom": true it could mimic the DOM in a certain way (it's then a fake DOM) to prevent errors.

var jsdom = require("jsdom").jsdom;
var doc = jsdom(markup, options);
var window = doc.defaultView;

https://github.com/tmpvar/jsdom

The document object holds en empty document of course but when it's available i prevents from errors.

When you don't want to implement this in this library maybe an hint would be nice to the users. Because it makes the development in react easier without caring about the availability of the window/document object etc.

Feature request - return promise from server.js

It would be useful for me if you could return the wait_for_file promise from server.js (line 20 of server.js). Then I could access the server I am creating and do things with it (such as mounting it into a koa parent instance). I think it might be useful in general.

I am trying to have a page-server run as a separate process in development, the way you have it setup in webpack-react-redux-isomorphic-render-example, but then mount the page-server into the web-server in production, so it can all run under one port. This is so I can deploy to Heroku servers, which only allow you to use one port.

What do you think?

This is not for noobs...

Yeah, this is definitely hard to understand by novices like me, I've been reading and trying for a couple of hours but no bueno :/

Seems there would be one more drawback. How to handle fs?

Using universal-webpack, seems the whole server will be bundled.
In my case, there is a file using require-directory which may lookup a directory to require all the files.
Since the server is bundled, the lookup path will be different and of course the system cannot find the right directory to require the files as they are also bundled.
What is the recommend way to handle this?

Problems with build

Hello. I am trying to use this library in this cool template. I made a lot of modifications and attempts. But I am newbie in all this node and webpack stuff and I cannot make this work. I have created webpack\universal-webpack-settings.js file with code:

module.exports =
{
  server:
  {
    input: './server/index',
    output: './build/server.js'
  }
}

Then I have modified webpack\webpack.dev.babel.js and now it is:

const path = require('path');
const fs = require('fs');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const logger = require('../../server/logger');
const cheerio = require('cheerio');
const pkg = require(path.resolve(process.cwd(), 'package.json'));
const dllPlugin = pkg.dllPlugin;

// PostCSS plugins
const cssnext = require('postcss-cssnext');
const postcssFocus = require('postcss-focus');
const postcssReporter = require('postcss-reporter');

const plugins = [
];

module.exports = {

  entry: [
    path.join(process.cwd(), 'app/app.js'), // Start with js/app.js
  ],

  // Don't use hashes in dev mode for better performance
  output: {
    filename: '[name].js',
    chunkFilename: '[name].chunk.js',
  },

  // Add development plugins
  plugins: dependencyHandlers().concat(plugins), // eslint-disable-line no-use-before-define

  // Load the CSS in a style tag in development
  cssLoaders: 'style-loader!css-loader?localIdentName=[local]__[path][name]__[hash:base64:5]&modules&importLoaders=1&sourceMap!postcss-loader',

  // Process the CSS with PostCSS
  postcssPlugins: [
    postcssFocus(), // Add a :focus to every :hover
    cssnext({ // Allow future CSS features to be used, also auto-prefixes the CSS...
      browsers: ['last 2 versions', 'IE > 10'], // ...based on this browser list
    }),
    postcssReporter({ // Posts messages from plugins to the terminal
      clearMessages: true,
    }),
  ],

  // Tell babel that we want to hot-reload
  babelQuery: {      
  },

  // Emit a source map for easier debugging
  devtool: 'cheap-module-eval-source-map',
};

/**
 * Select which plugins to use to optimize the bundle's handling of
 * third party dependencies.
 *
 * If there is a dllPlugin key on the project's package.json, the
 * Webpack DLL Plugin will be used.  Otherwise the CommonsChunkPlugin
 * will be used.
 *
 */
function dependencyHandlers() {
  // Don't do anything during the DLL Build step
  if (process.env.BUILDING_DLL) { return []; }

  // If the package.json does not have a dllPlugin property, use the CommonsChunkPlugin
  if (!dllPlugin) {
    return [
      new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor',
        children: true,
        minChunks: 2,
        async: true,
      }),
    ];
  }

  const dllPath = path.resolve(process.cwd(), dllPlugin.path || 'node_modules/react-boilerplate-dlls');

  /**
   * If DLLs aren't explicitly defined, we assume all production dependencies listed in package.json
   * Reminder: You need to exclude any server side dependencies by listing them in dllConfig.exclude
   *
   * @see https://github.com/mxstbr/react-boilerplate/tree/master/docs/general/webpack.md
   */
  if (!dllPlugin.dlls) {
    const manifestPath = path.resolve(dllPath, 'reactBoilerplateDeps.json');

    if (!fs.existsSync(manifestPath)) {
      logger.error('The DLL manifest is missing. Please run `npm run build:dll`');
      process.exit(0);
    }

    return [
      new webpack.DllReferencePlugin({
        context: process.cwd(),
        manifest: require(manifestPath), // eslint-disable-line global-require
      }),
    ];
  }

  // If DLLs are explicitly defined, we automatically create a DLLReferencePlugin for each of them.
  const dllManifests = Object.keys(dllPlugin.dlls).map((name) => path.join(dllPath, `/${name}.json`));

  return dllManifests.map((manifestPath) => {
    if (!fs.existsSync(path)) {
      if (!fs.existsSync(manifestPath)) {
        logger.error(`The following Webpack DLL manifest is missing: ${path.basename(manifestPath)}`);
        logger.error(`Expected to find it in ${dllPath}`);
        logger.error('Please run: npm run build:dll');

        process.exit(0);
      }
    }

    return new webpack.DllReferencePlugin({
      context: process.cwd(),
      manifest: require(manifestPath), // eslint-disable-line global-require
    });
  });
}

/**
 * We dynamically generate the HTML content in development so that the different
 * DLL Javascript files are loaded in script tags and available to our application.
 */
function templateContent() {
  const html = fs.readFileSync(
    path.resolve(process.cwd(), 'app/index.html')
  ).toString();

  if (!dllPlugin) { return html; }

  const doc = cheerio(html);
  const body = doc.find('body');
  const dllNames = !dllPlugin.dlls ? ['reactBoilerplateDeps'] : Object.keys(dllPlugin.dlls);

  dllNames.forEach(dllName => body.append(`<script data-dll='true' src='/${dllName}.dll.js'></script>`));

  return doc.toString();
}

Then I have created such webpack\webpack.dev.client.babel.js:

var  client_configuration = require('universal-webpack').clientConfiguration; 
var settings = require('./universal-webpack-settings');
var base_configuration = require('./webpack.dev.babel');


const webpack = require('webpack');
const path = require('path');
const fs = require('fs');
const pkg = require(path.resolve(process.cwd(), 'package.json'));
const dllPlugin = pkg.dllPlugin;
const logger = require('../../server/logger');
const cheerio = require('cheerio');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const plugins = [
  new webpack.HotModuleReplacementPlugin(), // Tell webpack we want hot reloading
  new webpack.NoErrorsPlugin(),
  new HtmlWebpackPlugin({
    inject: true, // Inject all files that are generated by webpack, e.g. bundle.js
    templateContent: templateContent(), // eslint-disable-line no-use-before-define
  }),
];

/**
 * We dynamically generate the HTML content in development so that the different
 * DLL Javascript files are loaded in script tags and available to our application.
 */
function templateContent() {
  const html = fs.readFileSync(
    path.resolve(process.cwd(), 'app/index.html')
  ).toString();

  if (!dllPlugin) { return html; }

  const doc = cheerio(html);
  const body = doc.find('body');
  const dllNames = !dllPlugin.dlls ? ['reactBoilerplateDeps'] : Object.keys(dllPlugin.dlls);

  dllNames.forEach(dllName => body.append(`<script data-dll='true' src='/${dllName}.dll.js'></script>`));

  return doc.toString();
}


base_configuration.entry.splice(0,0,'eventsource-polyfill','webpack-hot-middleware/client');

base_configuration.plugins = base_configuration.plugins.concat(plugins);

base_configuration.babelQuery =  {
  presets: ['react-hmre'],
};

var final_configuration = require('./webpack.base.babel')(base_configuration);


module.exports = client_configuration(final_configuration, settings);

Then I have created webpack\webpack.dev.server.babel.js:

var  server_configuration = require('universal-webpack').server_configuration;
var settings = require('./universal-webpack-settings');
var base_configuration = require('./webpack.dev.babel');

var configuration = require('./webpack.base.babel')(base_configuration);

module.exports = server_configuration(configuration, settings)

Then I have modifyed server\index.js:

const express = require('express');
const logger = require('./logger');

const argv = require('minimist')(process.argv.slice(2));
const setup = require('./middlewares/frontendMiddleware');
const isDev = process.env.NODE_ENV !== 'production';
const ngrok = (isDev && process.env.ENABLE_TUNNEL) || argv.tunnel ? require('ngrok') : false;
const resolve = require('path').resolve;

// If you need a backend, e.g. an API, add your custom backend-specific middleware here
// app.use('/api', myApi);

// In production we need to pass these values in instead of relying on webpack
const app = setup(express(), {
  outputPath: resolve(process.cwd(), 'build'),
  publicPath: '/',
});

// get the intended port number, use port 3000 if not provided
const port = argv.port || process.env.PORT || 3000;



// Start your app.
module.exports = function()
{
  console.log('server callback');
  app.listen(port, (err) => {
    console.log('server callback');
    if (err) {
      return logger.error(err.message);
    }

    // Connect to ngrok in dev mode
    if (ngrok) {
      ngrok.connect(port, (innerErr, url) => {
        if (innerErr) {
          return logger.error(innerErr);
        }

        logger.appStarted(port, url);
      });
    } else {
      logger.appStarted(port);
    }
  });
}

Finally I have created server\start-server.js file:

var server = require('universal-webpack').server;
var settings =  require('../internals/webpack/universal-webpack-settings')
var configuration = require('../internals/webpack/webpack.dev.babel');

var final_conf = require('../internals/webpack/webpack.base.babel')(configuration);
server(final_conf, settings)

After this I have modified server\middlewares\frontendMiddleware.js file and replaced this:

//const webpackConfig = require('../../internals/webpack/webpack.dev.babel');
const webpackConfig = require('../../internals/webpack/webpack.dev.client.babel');

Also I have modified start task in package.json:

"start": "cross-env NODE_ENV=development webpack --config internals/webpack/webpack.dev.server.babel.js && node server/start-server",

After alll this stuff, when I run start task I have following ouput (and server is not started):

cross-env NODE_ENV=development webpack --config internals/webpack/webpack.dev.server.babel.js && node server/start-server
./internals/webpack 160 bytes {0} [built]
./server/middlewares 160 bytes {0} [built]
+ 35 hidden modules

When I have tried to run result bundle file manually, I am getting the following error:

Error: Cannot find module 'components/Img'

If you have time, maybe you will help me. Or maybe it is bug in libarary, I do not know. And by the way, you should remove russian comments from sample application code ))) I am speaking about хз, нужно ли сжатие в node.js: мб лучше поставить впереди nginx'ы, . Espessialy you shoukd remove хз))

How to handle externals in server build

From what I gather this library will make all server modules "externals" yes? My server build file now contains references such as:

/*!*****************************************!*\
  !*** external "server/components/Html" ***!
  \*****************************************/
/***/ function(module, exports) {
  module.exports = require("server/components/Html");
/***/ },

That it cannot resolve as server/components/Html doesn't exist in the build directory. Ive peeked at the sample repo but could not locate how to handle this. What is the recommended process to get these files build or integrated with the server build?

Thanks

Node failing when it reaches scss imports in react components

Hi. I have attempted to set up universal webpack for my project but I cannot seem to get it running. I keep running into the following error:

SyntaxError: /Users/Aaron/Documents/Frontend/src_react/app/common/bootstrap-components/Container.scss: Unexpected token, expected ( (1:8)
> 1 | @import "sass/variables";
    |         ^
  2 | 
  3 | .container,
  4 | .container-fluid {
    at Parser.pp$5.raise (/Users/Aaron/Documents/Frontend/node_modules/babylon/lib/index.js:4215:13)
    at Parser.pp.unexpected (/Users/Aaron/Documents/Frontend/node_modules/babylon/lib/index.js:1599:8)
    at Parser.pp$3.parseExprAtom(/Users/Aaron/Documents/Frontend/node_modules/babylon/lib/index.js:3442:14)
    at Parser.parseExprAtom (/Users/Aaron/Documents/Frontend/node_modules/babylon/lib/index.js:6307:22)
    at Parser.pp$3.parseExprSubscripts (/Users/Aaron/Documents/Frontend/node_modules/babylon/lib/index.js:3305:19)
    at Parser.pp$3.parseMaybeUnary (/Users/Aaron/Documents/Frontend/node_modules/babylon/lib/index.js:3285:19)
    at Parser.pp$3.parseExprOps (/Users/Aaron/Documents/Frontend/node_modules/babylon/lib/index.js:3215:19)
    at Parser.pp$3.parseMaybeConditional (/Users/Aaron/Documents/Frontend/node_modules/babylon/lib/index.js:3192:19)
    at Parser.pp$3.parseMaybeAssign (/Users/Aaron/Documents/Frontend/node_modules/babylon/lib/index.js:3155:19)
    at Parser.parseMaybeAssign (/Users/Aaron/Documents/Frontend/node_modules/babylon/lib/index.js:5603:20)

I import scss files into my react components which is what causes this error. It seems that node gets confused when that happens. How can I fix this?

This is my webpack.config.client.js:

import { clientConfiguration } from 'universal-webpack'
import settings from './universal-webpack-settings'
import configuration from './webpack.config'

export default clientConfiguration(configuration, settings)

This is my webpack.config.server.js:

import { serverConfiguration } from 'universal-webpack'
import settings from './universal-webpack-settings'
import configuration from './webpack.config'

export default serverConfiguration(configuration, settings)

This is my start-server.js:

import { server } from 'universal-webpack'
import settings from './universal-webpack-settings'
import configuration from './webpack.config'

server(configuration, settings);

This is my server.js:

import React from 'react';
import path from 'path';
import http from 'http';
import express from 'express';
import httpProxy from 'http-proxy';
import { match, createRoutes, RouterContext } from 'react-router';
import { renderToString } from 'react-dom/server';
import { Provider } from 'react-redux';

import configureStore from 'app/configureStore';
import HomeRouter from 'app/home/components/HomeRouter';
import template from 'app/template';

export default function(parameters) {
  const app = new express()
  const server = new http.Server(app)
  const routes = createRoutes(HomeRouter());
  const preloadedState = {
    session: {
      currentUser: null
    }
  };
  const store = configureStore(preloadedState);
  app.use(express.static(path.join(__dirname, 'build/assets')))
  const backend_url = process.env.BACKEND_URL || "http://localhost:8000/";
  const proxy = httpProxy.createProxyServer({ target: backend_url, changeOrigin: true })
  app.use('/api', (req, res) => proxy.web(req, res))

  app.use((req, res) => {
    match(
      { routes, location: req.url },
      (error, redirectLocation, renderProps) => {
        if (error) {
            res.status(500)
            return res.send('Server error')
        }
        const page = renderToString(
          <Provider store={store}>
            <RouterContext {...renderProps} />
          </Provider>
        )
        res.status(200)
        res.send(template({
          body: page
        }))
      }
    )
  })

  server.listen()
}

and this is my webpack.config.js:

const path = require('path');
const webpack = require('webpack');
const autoprefixer = require('autoprefixer');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const context = path.resolve(__dirname);

var config = {
  entry: path.join(__dirname, './src_react/app/entry.jsx'),
  context: context,
  output: {
    path: path.join(__dirname, '/build'),
    filename: '[name]-[hash].js',
    publicPath: '/'
  },
  module: {
    loaders: [
      {
        test: /\.json$/,
        loader: 'json'
      },
      {
        test: [/\.jsx?$/, /\.js?$/],
        exclude: /(node_modules|bower_components)/,
        loader: 'babel'
      },
      {
        test: /\.png$/,
        loader: 'url-loader?limit=100000'
      },
      {
        test: /\.jpg$/,
        loader: 'file-loader'
      },
      {
        test: /\.gif$/,
        loaders: [
          'file?hash=sha512&digest=hex&name=[hash].[ext]',
          'image-webpack?bypassOnDebug&optimizationLevel=7&interlaced=false'
        ]
      },
      {
        test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url?limit=10000&mimetype=application/font-woff'
      },
      {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url?limit=10000&mimetype=application/octet-stream'
      },
      {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'file'
      },
      {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url?limit=10000&mimetype=image/svg+xml'
      },
      {
        test: /\.otf(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'file-loader?name=fonts/[name].[ext]'
      },
      {
        test: /\.scss$/,
        loaders: ['style', 'css', 'resolve-url', 'sass?sourceMap']
      },
      {
        test: /\.css$/,
        loader: 'style-loader!css-loader'
      }
    ]
  },
  resolve: {
    root: [
      path.resolve('./src_react')
    ],
    extensions: ['', '.js', '.jsx', '.css', '.scss'],
    alias: {
      'ie': 'component-ie'
    }
  },
  sassLoader: {
    includePaths: [path.resolve(__dirname, "./src_react")]
  },
  postcss: [
    autoprefixer
  ],
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, '/src_react/index.tmpl.html')
    }),
    new webpack.DefinePlugin({
      'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development') }
    }),
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery"
    })
  ]
};

module.exports = config;

Wait for file triggering before file is finished writing

I reported this before at some point, but it's back and is happening more often now for my growing project. When I am compiling my project using 'npm run dev' I run into this error every few times I build:

[universal-webpack] Your server source file must export a function. Got '{}'

I find that if I add a 1 second timeout to 'wait for file.js' I get rid of the error:

//around line 47
if (condition_is_met)
{
  setTimeout(done, 1000);
  // instead of return done()
}

I believe what is happening is while the file is writing, the filesystem will report that it exists. But then when the file is loaded via 'require', the contents are not fully written, so it fails and returns an empty {}. By putting in the 1 second delay, the file is able to finish writing.

An alternative solution would be to make server.js retry requiring 'starter' (after a delay) when it doesn't return a function. Let me know if you need further info.

Usage with davezuko's starter kit

I'm trying to create a universal React Redux project based on some of the fundamentals of davezuko's starter kit. Found your stuff but it seems to be very unclear how to achieve it so I'm turning to you here for some instructions with the configuration.
I also opened a question here
Thanks in advance!

Error: [universal-webpack] Your server source file must export a function

I try to start the server build server like following:

nodemon -L ./start-server.js --exec babel-node --watch ./build/server

The server.js (built with webpack located in ./build/server/server.js) have a special webpack exported format and start-server.js and universal-webpack/server.js run in a normal node environment and tries to include the buit server.js here

https://github.com/halt-hammerzeit/universal-webpack/blob/master/source/server.js#L41

The result is that the "starter" variable become following:

[ 0, 1 ]

What did I miss?

server object is empty

In import { server } from 'universal-webpack'; the server object is empty.

universal-webpack exports:

{ server: undefined,
  server_configuration: [Function: server_configuration],
  client_configuration: undefined,
  prepare: undefined,
  serverConfiguration: [Function: server_configuration],
  clientConfiguration: undefined }

Webpack 2 tree-shaking

Hello @halt-hammerzeit!

First of all I'd like to thank you for the isomorphic tools - splendid work.

I'm now looking into how well I could incorporate this repo into my future work and it seems I stumbled upon something I can't really find a way around.

I created a fork of your example repo here and I did some changing around. One notable thing to notice is that I switched off module parsing using babel for es2015 modules, because WP2 natively understands it and it's how it does treeshaking.

Now - the problem.

TypeError: Cannot read property 'a' of undefined
    at Object.<anonymous> (/Users/elodszopos/study/webpack-react-redux-isomorphic-render-example/build/server/webpack:/code/client/react-isomorphic-render.js:11:3)
    at Object.module.exports.module.exports.apiServer.http.host (/Users/elodszopos/study/webpack-react-redux-isomorphic-render-example/build/server/server.js:256:30)
    at __webpack_require__ (/Users/elodszopos/study/webpack-react-redux-isomorphic-render-example/build/server/webpack:/webpack/bootstrap 5b78232aefaf71c0b543:19:1)
    at Object.<anonymous> (/Users/elodszopos/study/webpack-react-redux-isomorphic-render-example/build/server/server.js:1686:90)
    at __webpack_require__ (/Users/elodszopos/study/webpack-react-redux-isomorphic-render-example/build/server/webpack:/webpack/bootstrap 5b78232aefaf71c0b543:19:1)
    at /Users/elodszopos/study/webpack-react-redux-isomorphic-render-example/build/server/webpack:/webpack/bootstrap 5b78232aefaf71c0b543:65:1
    at Object.<anonymous> (/Users/elodszopos/study/webpack-react-redux-isomorphic-render-example/build/server/server.js:70:10)
    at Module._compile (module.js:556:32)
    at Object.Module._extensions..js (module.js:565:10)
    at Module.load (module.js:473:32)
    at tryModuleLoad (module.js:432:12)
    at Function.Module._load (module.js:424:3)
    at Module.require (module.js:483:17)
    at require (internal/module.js:20:19)
    at /Users/elodszopos/study/webpack-react-redux-isomorphic-render-example/node_modules/universal-webpack/source/server.js:42:19

Upon doing npm run development-page-server I run into this nasty little bugger. From what I understand and if I'm not mistaken, the server part of universal-webpack is expecting the bundled server.js to be in a specific format - and since I switched to WebPack2 it's not exactly that. So something goes wrong.

Do you maybe have any insight into what's going on?

Cannot find module css/sass-loader

When starting the server:

Error: Cannot find module '!!./../../../node_modules/css-loader/index.js!./../../../node_modules/sass-loader/index.js!./style.scss'
    at Function.Module._resolveFilename (module.js:438:15)
    at Function.Module._load (module.js:386:25)
    at Module.require (module.js:466:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (server.js:775:19)
    at __webpack_require__ (server.js:21:30)
    at Object.<anonymous> (server.js:762:16)
    at __webpack_require__ (server.js:21:30)
    at Object.<anonymous> (server.js:459:2)
    at __webpack_require__ (server.js:21:30)

[nodemon] app crashed - waiting for file changes before starting...

How do we handle Multiple Entry points.

Hi @halt-hammerzeit

I know this might not be an issue , just putting as discussion thread.

Say I have multiple entry points in my webpack.config.js. e.g Home.js , About.js

Now on server side we have only one HTML file , how do we stop loading About.js while visiting Home ?

`style` loader not replaced with fake-style-loader

In a webpack configuration i can refer to a named loader as name-loader or just with its name. If i do the latter, universal webpack will fail replacing style with fake-style-loader while generating server conf.

i.e.

...
    loader: 'style!css'
...

This bug results in style loader to be included in the built output and node.js won't be able to run it as style-loader only works in the browser.

in head element node, only can insert one child, but i got a lot cdn link to append

import React from 'react'
import webpageServer from 'react-isomorphic-render/server'
import { devtools } from 'universal-webpack'

import common from '../client/reactIsomorphicRender'
import Log from '../common/log'

const log = Log('webpage renderer')


export default function(parameters) {

    const server = webpageServer({
        assets: (url) => {
            const result = clone(parameters.chunks())
            result.entry = 'main'

            // if(_development_){
            //     delete require.cache[require.resolve('../../assets/images/icon/cat_64x64.png')]
            // }

            // Add favicon
            result.icon = require('../../assets/images/icon/cat_64x64.png')

            return result

        },

        application: {
            host: configuration.web_server.http.host,
            port: configuration.web_server.http.port
        },

        html: {
            head: (url) => {
                // if(_development_) {
                //     const script = devtools({ ...parameters, entry: 'main' })
                //     return <script dangerouslySetInnerHTML = {{ __html: script }} />
                // }
                return (
                        <link href="//cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet"></link>
                        <link rel="stylesheet" href="https://npmcdn.com/react-bootstrap-table/dist/react-bootstrap-table-all.min.css"></link>
                )

            }
        },
        middleware: [function(context, next){
            global.navigator = {userAgent: context.request.header['user-agent']};
            next()
        }]
    },
    common)

    server.listen(configuration.webpage_server.http.port, function(error){

        if(error) {
            log.error('Webpage rendering server shutdown due to an error', error)
            throw error
        }

        log.info(`Webpage server is listening at http://localhost:${configuration.webpage_server.http.port}`)
    })
}

can't insert two links in head by config html.head

html: {
            head: (url) => {
                // if(_development_) {
                //     const script = devtools({ ...parameters, entry: 'main' })
                //     return <script dangerouslySetInnerHTML = {{ __html: script }} />
                // }
                return (
                        <link href="//cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet"></link>
                        <link rel="stylesheet" href="https://npmcdn.com/react-bootstrap-table/dist/react-bootstrap-table-all.min.css"></link>
                )

            }
        },

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.