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

WIP of converting examples to Webpack v2 #742

Merged
merged 10 commits into from
Mar 6, 2017
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ After running a test, you can view the coverage results SimpleCov reports by ope

To test `spec/dummy` against Turbolinks 5, install the gem by running `ENABLE_TURBOLINKS_5=TRUE bundle install` in the `spec/dummy` directory before running `rake`.

Run `rake -T` or `rake -D` to see testing options.

`rake all_but_examples` is typically best for developers, except if any generators changed.

See below for verifying changes to the generators.

### Debugging
Start the sample app like this for some debug printing:

Expand All @@ -216,6 +222,8 @@ The main installer can be run with ```rails generate react_on_rails:install```
### Testing the Generator
The generators are covered by generator tests using Rails's generator testing helpers, but it never hurts to do a sanity check and explore the API. See [generator_testing_script.md](generator_testing_script.md) for a script on how to run the generator on a fresh project.

`rake run_rspec:example_basic` is a great way to run tests on one generator. Once that works, you should run `rake run_rspec:examples`. Be aware that this will create a hug number of files under a `/gen-examples` directory. You should be sure to exclude this directory from your IDE and delete it once your testing is done.

### Linting
All linting is performed from the docker container for CI. You will need docker and docker-compose installed locally to lint code changes via the lint container. You can lint locally by running `npm run lint && npm run flow`

Expand Down
2 changes: 1 addition & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ end
desc "Run all tests and linting"
task default: tasks

desc "All actions but no examples. Good for local developer run."
desc "All actions but no examples, good for local developer run."
task all_but_examples: ["run_rspec:all_but_examples", "lint"]
23 changes: 23 additions & 0 deletions docs/additional-reading/webpack-v1-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Webpack V1 Tips

The following only apply to Webpack V1. Take 1 hour and update to v2! It's worth it!

## Use the `--bail` Option When Running Webpack for CI or Deployments if using Webpack V1
For your scripts that statically build your Webpack bundles, use the `--bail` option. This will ensure that CI and your product deployment **halt** if Webpack cannot complete! For more details, see the documentation for [Webpack's `--bail` option](https://webpack.js.org/configuration/other-options/#bail). Note, you might not want to use the `--bail` option if you just want to depend on Webpack returning a non-zero error code and you want to see all the errors, rather than only the first error.


## Entry Points
You should ensure you configure the entry points correctly for webpack if you want to break out libraries into a "vendor" bundle where your libraries are packaged separately from your app's code. If you send web clients your vendor bundle separately from your app bundles, then web clients might have the vendor bundle cached while they receive updates for your app.

You need both include `react-dom` and `react` as values for `entry`, like this:

```
entry: {

// See use of 'vendor' in the CommonsChunkPlugin inclusion below.
vendor: [
'babel-core/polyfill',
'react',
'react-dom',
],
```
18 changes: 5 additions & 13 deletions docs/additional-reading/webpack.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,17 @@ You can try out example app, [shakacode/react-webpack-rails-tutorial](https://gi
## Webpack v1 or v2?
We recommend using Webpack version 2.2.1 or greater.

## Use the `--bail` Option When Running Webpack for CI or Deployments
For your scripts that statically build your Webpack bundles, use the `--bail` option. This will ensure that CI and your product deployment **halt** if Webpack cannot complete! For more details, see the documentation for [Webpack's `--bail` option](https://webpack.js.org/configuration/other-options/#bail). Note, you might not want to use the `--bail` option if you just want to depend on Webpack returning a non-zero error code and you want to see all the errors, rather than only the first error.

## yarn or npm?
Yarn is the current recommendation!

## Entry Points

You should ensure you configure the entry points correctly for webpack if you want to break out libraries into a "vendor" bundle where your libraries are packaged separately from your app's code. If you send web clients your vendor bundle separately from your app bundles, then web clients might have the vendor bundle cached while they receive updates for your app.

You need both include `react-dom` and `react` as values for `entry`, like this:
Webpack v2 makes this very convenient! See:

* [Implicit Common Vendor Chunk](https://webpack.js.org/guides/code-splitting-libraries/#implicit-common-vendor-chunk)
* [Manifest File](https://webpack.js.org/guides/code-splitting-libraries/#manifest-file)


```
entry: {

// See use of 'vendor' in the CommonsChunkPlugin inclusion below.
vendor: [
'babel-core/polyfill',
'react',
'react-dom',
],
```
23 changes: 12 additions & 11 deletions lib/generators/react_on_rails/dev_tests_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@

module ReactOnRails
module Generators
FALLBACK_OPTION_FOR_NODE_MODULES = <<-TEXT
// This fixes an issue with resolving 'react' when using a local symlinked version
// of the node_package folder
modules: [
require('path').join(__dirname, 'node_modules'),
'node_modules',
],
},
plugins: [
TEXT

class DevTestsGenerator < Rails::Generators::Base
include GeneratorHelper
Rails::Generators.hide_namespace(namespace)
Expand Down Expand Up @@ -35,20 +46,10 @@ def change_package_json_to_use_local_react_on_rails_module
end

def change_webpack_client_base_config_to_include_fallback
text = <<-TEXT
},

// This fixes an issue with resolving 'react' when using a local symlinked version
// of the node_package folder
resolveLoader: {
fallback: [path.join(__dirname, 'node_modules')],
},
plugins: [
TEXT
sentinel = /^\s\s},\n\s\splugins: \[\n/
config = File.join(destination_root, "client", "webpack.config.js")
old_contents = File.read(config)
new_contents = old_contents.gsub(sentinel, text)
new_contents = old_contents.gsub(sentinel, FALLBACK_OPTION_FOR_NODE_MODULES)
File.open(config, "w+") { |f| f.puts new_contents }
end

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"presets": ["es2015", "stage-0", "react"]
"presets": ["es2015", "stage-2", "react"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,25 @@
},
"cacheDirectories": ["node_modules", "client/node_modules"],
"dependencies": {
"babel-cli": "^6.18.0",
"babel-core": "^6.21.0",
"babel-loader": "^6.2.10",
"babel-runtime": "^6.20.0",
"babel-polyfill": "^6.20.0",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-0": "^6.16.0",
"babel-cli": "^6.23.0",
"babel-core": "^6.23.1",
"babel-loader": "^6.3.2",
"babel-runtime": "^6.23.0",
"babel-polyfill": "^6.23.0",
"babel-preset-es2015": "^6.22.0",
"babel-preset-react": "^6.23.0",
"babel-preset-stage-2": "^6.22.0",
"es5-shim": "^4.5.9",
"expose-loader": "^0.7.1",
"imports-loader": "^0.7.0",
"react": "^15.4.1",
"react-dom": "^15.4.1",
"expose-loader": "^0.7.3",
"imports-loader": "^0.7.1",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-on-rails": "<%= VersionSyntaxConverter.new.rubygem_to_npm %>",
<%- if options.redux? -%>
"react-redux": "^5.0.1",
"react-redux": "^5.0.3",
"redux": "^3.6.0",
<%- end -%>
"webpack": "^1.14.0"
"webpack": "^2.2.1"
},
"devDependencies": {
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
/* eslint comma-dangle: ["error",
{"functions": "never", "arrays": "only-multiline", "objects":
"only-multiline"} ] */
{"functions": "never", "arrays": "only-multiline", "objects":
"only-multiline"} ] */

const webpack = require('webpack');
const path = require('path');

const devBuild = process.env.NODE_ENV !== 'production';
const nodeEnv = devBuild ? 'development' : 'production';

const config = {
entry: [
Expand All @@ -22,28 +20,26 @@ const config = {
},

resolve: {
extensions: ['', '.js', '.jsx'],
alias: {
react: path.resolve('./node_modules/react'),
'react-dom': path.resolve('./node_modules/react-dom'),
},
extensions: ['.js', '.jsx'],
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(nodeEnv),
},
}),
new webpack.EnvironmentPlugin({ NODE_ENV: 'development' }),
],
module: {
loaders: [
rules: [
{
test: require.resolve('react'),
loader: 'imports?shim=es5-shim/es5-shim&sham=es5-shim/es5-sham',
use: {
loader: 'imports-loader',
options: {
shim: 'es5-shim/es5-shim',
sham: 'es5-shim/es5-sham',
}
},
},
{
test: /\.jsx?$/,
loader: 'babel-loader',
use: 'babel-loader',
exclude: /node_modules/,
},
],
Expand All @@ -56,8 +52,5 @@ if (devBuild) {
console.log('Webpack dev build for Rails'); // eslint-disable-line no-console
module.exports.devtool = 'eval-source-map';
} else {
config.plugins.push(
new webpack.optimize.DedupePlugin()
);
console.log('Webpack production build for Rails'); // eslint-disable-line no-console
}
2 changes: 1 addition & 1 deletion node_package/.babelrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"presets": ["es2015", "stage-0", "react"],
"presets": ["es2015", "stage-2", "react"],
"plugins": [
"transform-flow-strip-types",
"transform-runtime"
Expand Down
42 changes: 21 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,35 @@
"doc": "docs"
},
"devDependencies": {
"babel-cli": "^6.18.0",
"babel-core": "^6.21.0",
"babel-loader": "^6.2.10",
"babel-cli": "^6.23.0",
"babel-core": "^6.23.1",
"babel-loader": "^6.3.2",
"babel-plugin-react-transform": "^2.0.2",
"babel-plugin-transform-flow-strip-types": "^6.21.0",
"babel-plugin-transform-runtime": "^6.15.0",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-0": "^6.16.0",
"babel-runtime": "^6.20.0",
"babel-plugin-transform-flow-strip-types": "^6.22.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.22.0",
"babel-preset-react": "^6.23.0",
"babel-preset-stage-2": "^6.22.0",
"babel-runtime": "^6.23.0",
"babel-tape-runner": "^2.0.1",
"babel-types": "^6.21.0",
"babel-types": "^6.23.0",
"babelify": "^7.3.0",
"blue-tape": "^1.0.0",
"eslint": "^3.9.1",
"eslint-config-shakacode": "^13.2.1",
"eslint-plugin-import": "^2.1.0",
"eslint-plugin-jsx-a11y": "^2.2.3",
"eslint-plugin-react": "^6.6.0",
"flow-bin": "^0.37.4",
"jsdom": "^9.9.1",
"react": "^15.4.1",
"react-dom": "^15.4.1",
"eslint": "^3.16.1",
"eslint-config-shakacode": "^14.1.1",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-react": "^6.10.0",
"flow-bin": "^0.40.0",
"jsdom": "^9.11.0",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-transform-hmr": "^1.0.4",
"redux": "^3.6.0",
"release-it": "^2.5.3",
"release-it": "^2.5.4",
"tap-spec": "^4.1.1",
"tape": "^4.6.3",
"webpack": "^1.14.0"
"webpack": "^2.2.1"
},
"peerDependencies": {
"babel-runtime": ">= 6",
Expand Down
6 changes: 5 additions & 1 deletion rakelib/run_rspec.rake
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,11 @@ task :js_tests do
sh "yarn run test"
end

desc "Runs all tests. Run `rake -D run_rspec` to see all available test options"
msg = <<-DESC
Runs all tests, run `rake -D run_rspec` to see all available test options.
"rake run_rspec:example_basic" is a good way to run only one generator test.
DESC
desc msg
task run_rspec: ["run_rspec:run_rspec"]

private
Expand Down
3 changes: 1 addition & 2 deletions spec/dummy/client/.babelrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{
"presets": ["es2015", "stage-0", "react"],
"plugins": ["syntax-decorators"]
"presets": ["es2015", "stage-2", "react"]
}
3 changes: 0 additions & 3 deletions spec/dummy/client/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,4 @@
extends: eslint-config-shakacode

rules:
no-console: 0
import/no-unresolved: 0
import/no-extraneous-dependencies: 0
react/forbid-prop-types: 0
6 changes: 6 additions & 0 deletions spec/dummy/client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ npm-check-updates -u -a
yarn
```

Another option for upgrading:

```
yarn upgrade
```

Then confirm that the hot reload server and the rails server both work fine. You
may have to delete `node_modules`.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import React from 'react';
export default class CacheDisabled extends React.Component {

componentWillUnmount() {
console.log('CacheDisabled#componentWillUnmount')
// eslint-disable-next-line no-console
console.log('CacheDisabled#componentWillUnmount');
}

render() {
Expand Down
2 changes: 1 addition & 1 deletion spec/dummy/client/app/components/EchoProps.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ const EchoProps = (props) => (
</div>
);

export default EchoProps
export default EchoProps;
1 change: 1 addition & 0 deletions spec/dummy/client/app/components/HelloWorld.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class HelloWorld extends React.Component {
}

render() {
// eslint-disable-next-line no-console
console.log('HelloWorld demonstrating a call to console.log in ' +
'spec/dummy/client/app/components/HelloWorld.jsx:18');

Expand Down
2 changes: 2 additions & 0 deletions spec/dummy/client/app/components/HelloWorldRedux.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export default class HelloWorldRedux extends React.Component {

// If this creates an alert, we have a problem!
// see file node_package/src/scriptSanitizedVal.js for the fix to this prior issue.

/* eslint-disable no-console */
console.log('This is a script:"</div>"</script> <script>alert(\'WTF1\')</script>');
console.log('Script2:"</div>"</script xx> <script>alert(\'WTF2\')</script xx>');
console.log('Script3:"</div>"</ SCRIPT xx> <script>alert(\'WTF3\')</script xx>');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React from 'react';
// Example of logging and throw error handling

const HelloWorldWithLogAndThrow = (props, context) => {
/* eslint-disable no-console */
console.log('console.log in HelloWorld');
console.warn('console.warn in HelloWorld');
console.error('console.error in HelloWorld');
Expand Down
1 change: 1 addition & 0 deletions spec/dummy/client/app/components/RailsContext.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { PropTypes } from 'react';
import _ from 'lodash';

function renderContextRows(railsContext) {
// eslint-disable-next-line no-console
console.log('railsContext.serverSide is ', railsContext.serverSide);
return _.transform(railsContext, (accum, value, key) => {
if (key !== 'serverSide') {
Expand Down
2 changes: 1 addition & 1 deletion spec/dummy/client/app/startup/ClientRenderedHtml.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ import EchoProps from '../components/EchoProps';
* Note, this is a fictional example, as you'd only use a generator function if you wanted to run
* some extra code, such as setting up Redux and React-Router.
*/
export default (props, railsContext) => (
export default (props, _railsContext) => (
<EchoProps {...props} />
);
Loading