Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Webpack - For Production #129

Closed
spyalert01 opened this issue Aug 20, 2015 · 12 comments
Closed

Webpack - For Production #129

spyalert01 opened this issue Aug 20, 2015 · 12 comments

Comments

@spyalert01
Copy link

So far most of the example uses

var app = new WebpackDevServer(compiler, {
  contentBase: '/public/',
  proxy: {'/graphql': `http://localhost:${GRAPHQL_PORT}`},
  publicPath: '/js/',
  stats: {colors: true}
});

This is actually run time generation. WebpackDevServer should be more for Development. If we want to have the same for production,

  1. How should we rewrite the server.js?
  2. webpack.config.js?

Thanks

@steveluscher
Copy link
Contributor

There are many ways to go to production, and Webpack is only one of them. If you chose to go with Webpack to build your static assets, the configuration that you see in server.js would make up most of your webpack.config.js:

// In webpack.config.js
module.exports = {
  entry: path.resolve(__dirname, 'js', 'app.js'),
  eslint: {
    configFile: '.eslintrc'
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel',
        query: {
          stage: 0,
          plugins: ['./build/babelRelayPlugin']
        }
      },
      {
        test: /\.js$/,
        loader: 'eslint'
      }
    ]
  },
  output: {filename: 'app.js', path: '/'}
}

Running webpack -p with that config should yield a productionized JavaScript bundle that you can include in your HTML file and serve using any server you like (express, nginx, et cetera).

From that point, you might want to investigate features like code splitting and multiple entry points to split up your bundles as your app grows.

I hope that this gives you a headstart. To learn more about how others are deploying their React applications in production, consider asking around on the Reactiflux Slack. There's a #webpack group in there. You can sign up here: http://www.reactiflux.com/

@spyalert01
Copy link
Author

HI @steveluscher
Thanks for your answer.
The part that you show, I understand, and I know how to deal with it. But how about the part that I show. How can I move that part out from server.js to webpack.config.js?

@fortruce
Copy link

@spyalert01

The part that you show in your original example is creating a development http server. The settings you are passing to WebpackDevServer are not relevant to a production server deployment.

As @steveluscher said, you can use webpack -p to have Webpack bundle all of your assets (in the exmaple webpack.config.js this would output app.js). Then, you would have your production web server, express for example, serve the bundle generated by Webpack, app.js, alongside your index.html page (and other static non-bundled assets).

Webpack does not provide a production web server, it just bundles your assets together. You must then serve those bundled assets yourself. See this blog post for examples on how to set this up.

@spyalert01
Copy link
Author

@fortune
so
var app = new WebpackDevServer(compiler, {
contentBase: '/public/',
proxy: {'/graphql': http://localhost:${GRAPHQL_PORT}},
publicPath: '/js/',
stats: {colors: true}
});
must be in the server.js in order to interact with GraphQL data right?

I brought this up because I read some article saying webpackdevserver is for development environment. Not for production as it will slow down the system.

Which I also realise on the star-wars, and treasurehunt, it really take time to start the server for testing purposes.

@clentfort
Copy link

Right, WebpackDevServer is for development only!
It is used in the examples because it does not require any additional packages such as express or any other server implementation and provides easy logging to the command line. It is not recommended to use it for any form of a production webserver!

Have a look at relay-starter-kit which is a nice starting point for a new relay application.

@fortruce
Copy link

@spyalert01
You should use a completely separate server.js file for production. You do not want to include anything webpack specific in your production server.js. Webpack is a build step - you should use it to generate the final application bundle you then serve.

For example, your production server.js might be simply:

import express from 'express';
import graphQLHTTP from 'express-graphql';
import path from 'path';

// import your GraphQL schema file to generate the GraphQL server
import { Schema } from './data/schema';

// create your base web server
const app = express();

// serve all requests to `/graphql` to the GraphQL Server
app.use('/graphql', graphQLHTTP({ schema: Schema, pretty: true }));

// serve your static assets (application bundle created by webpack)
app.use(express.static(path.join(__dirname, 'public'));

app.listen(8080, (err) => {
  if (err)
    return console.error(err);
  console.log('Production server now running on localhost:8080');
});

This is assuming you have copied the bundled assets generated by webpack, your app.js output of webpack -p, to the public/ directory.

@spyalert01
Copy link
Author

I see. thanks

@chiedo
Copy link

chiedo commented Nov 6, 2015

Hi all,
I'm struggling here. I have a Relay app working perfectly when running locally. But when I use webpack to generate my production build, I keep getting this error in the console.

Uncaught Error: Invariant Violation: RelayQL: Unexpected invocation at runtime. Either the Babel transform was not set up, or it failed to identify this call site. Make sure it is being used verbatim as `Relay.QL`.

This is my production webpack config:

/* eslint no-var: 0 */
var path = require('path');

// In webpack.config.js
module.exports = {
  entry: path.resolve(__dirname, 'src', 'react', 'app.js'),
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel',
        query: {
          stage: 0,
          plugins: ['./babelRelayPlugin'],
        },
      },
    ],
  },
  output: {filename: 'app.js', path: path.join(__dirname,'static', 'dist','js')},
};

I am running my build with the following command:

webpack -p --config webpack.config.prod.js

Any help would be appreciated.

@chiedo
Copy link

chiedo commented Nov 6, 2015

LOL. Wow. The above was working, I just had a typo.

'static', 'dist'

should have been

'dist', 'static'

@steveluscher
Copy link
Contributor

👍

@koistya
Copy link

koistya commented Jun 15, 2016

@standardtoaster is there a recipe how to do code splitting and the stuff like this (taken from rsk):

import Component from './Component'; // <= breaks code-splitting

const route = {
  path: '/component',
  queries: {
    viewer: Relay.QL`query {
      viewer {
        ${Component.getFragment(..)}
      }
    }`
  },
  async action() {
    return { title: 'Code-splitting Demo', component: await System.load('./Component') };
  }
}

@koistya
Copy link

koistya commented Jun 15, 2016

@standardtoaster correct me if I'm wrong, if you're using code-splitting, you can perform a GraphQL/Relay query only after the component was loaded into run-time? (e.g. you can't download data and some component that requires that data at the same time)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants