mirror of
https://github.com/react-webpack-generators/generator-react-webpack.git
synced 2025-12-08 18:01:59 +00:00
Project test configuration and updated README
Signed-off-by: Simon Bailey <simon@newtriks.com>
This commit is contained in:
parent
b1562cd74c
commit
fb2e98d63e
176
README.md
176
README.md
@ -1,46 +1,168 @@
|
||||
# generator-react-webpack [](https://travis-ci.org/newtriks/generator-react-webpack)
|
||||
# generator-react-webpack [](https://travis-ci.org/newtriks/generator-react-webpack) [](http://gruntjs.com/)
|
||||
|
||||
A generator for [Yeoman](http://yeoman.io).
|
||||
> Yeoman generator for [ReactJS](http://facebook.github.io/react/) - lets you quickly set up a project including karma test runner and [Webpack](http://webpack.github.io/) module system.
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
### What is Yeoman?
|
||||
|
||||
Trick question. It's not a thing. It's this guy:
|
||||
|
||||

|
||||
|
||||
Basically, he wears a top hat, lives in your computer, and waits for you to tell him what kind of application you wish to create.
|
||||
|
||||
Not every new computer comes with a Yeoman pre-installed. He lives in the [npm](https://npmjs.org) package repository. You only have to ask for him once, then he packs up and moves into your hard drive. *Make sure you clean up, he likes new and shiny things.*
|
||||
## Usage
|
||||
|
||||
Install `generator-react-webpack`:
|
||||
```
|
||||
$ npm install -g yo
|
||||
npm install -g generator-react-webpack
|
||||
```
|
||||
|
||||
### Yeoman Generators
|
||||
|
||||
Yeoman travels light. He didn't pack any generators when he moved in. You can think of a generator like a plug-in. You get to choose what type of application you wish to create, such as a Backbone application or even a Chrome extension.
|
||||
|
||||
To install generator-react-webpack from npm, run:
|
||||
|
||||
Make a new directory, and `cd` into it:
|
||||
```
|
||||
$ npm install -g generator-react-webpack
|
||||
mkdir my-new-project && cd $_
|
||||
```
|
||||
|
||||
Finally, initiate the generator:
|
||||
|
||||
Run `yo react-webpack`, optionally passing an app name:
|
||||
```
|
||||
$ yo react-webpack
|
||||
yo react-webpack [app-name]
|
||||
```
|
||||
|
||||
### Getting To Know Yeoman
|
||||
Run `grunt` for building and `grunt serve` for preview in the browser at [localhost](http://localhost:8000).
|
||||
|
||||
Yeoman has a heart of gold. He's a person with feelings and opinions, but he's very easy to work with. If you think he's too opinionated, he can be easily convinced.
|
||||
## Generators
|
||||
|
||||
If you'd like to get to know Yeoman better and meet some of his friends, [Grunt](http://gruntjs.com) and [Bower](http://bower.io), check out the complete [Getting Started Guide](https://github.com/yeoman/yeoman/wiki/Getting-Started).
|
||||
Available generators:
|
||||
|
||||
* [react-webpack](#app) (aka [react-webpack:app](#app))
|
||||
* [react-webpack:component](#component)
|
||||
|
||||
**Note: Generators are to be run from the root directory of your app.**
|
||||
|
||||
### App
|
||||
|
||||
Sets up a new ReactJS app, generating all the boilerplate you need to get started. The app generator also facilitates the following:
|
||||
|
||||
1. Configures a Gruntfile to run the app on a local server.
|
||||
2. Configures Webpack to modularise the app enabling [loading of various file formats](http://webpack.github.io/docs/loader-list.html) e.g. JSON, CSS, PNG, etc.
|
||||
3. Configures [Karma](http://karma-runner.github.io) to run all tests.
|
||||
4. Watches for changes and recompiles JS and refreshes the browser.
|
||||
|
||||
Example:
|
||||
```bash
|
||||
yo react-webpack
|
||||
```
|
||||
|
||||
### Component
|
||||
|
||||
Generates a [JSX](http://facebook.github.io/react/docs/jsx-in-depth.html) component in `src/scripts/components` and it's corresponding test in `src/spec/components`.
|
||||
|
||||
Example:
|
||||
```bash
|
||||
yo react-webpack:component foo
|
||||
```
|
||||
|
||||
Produces `src/scripts/components/Foo.js` (*javascript - JSX*):
|
||||
```
|
||||
/**
|
||||
* @jsx React.DOM
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('react/addons');
|
||||
|
||||
var Foo = React.createClass({
|
||||
/*jshint ignore:start */
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<p>Content for Foo</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
/*jshint ignore:end */
|
||||
});
|
||||
|
||||
module.exports = Foo;
|
||||
```
|
||||
|
||||
And `test/spec/components/Foo.js` (*javascript - jasmine*):
|
||||
```
|
||||
|
||||
'use strict';
|
||||
|
||||
describe('Foo', function () {
|
||||
var Foo, component;
|
||||
|
||||
beforeEach(function () {
|
||||
Foo = require('../../../src/scripts/components/Foo');
|
||||
component = Foo();
|
||||
});
|
||||
|
||||
it('should create a new instance of Foo', function () {
|
||||
expect(component).toBeDefined();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Running `grunt test` will run the unit tests with karma. Tests are written using [Jasmine](http://pivotal.github.io/jasmine/) by default.
|
||||
|
||||
## Further Information
|
||||
|
||||
### Project Structure
|
||||
|
||||
The react-webpack generator automates the setup of a [ReactJS](http://facebook.github.io/react/) project using the specific structure detailed below:
|
||||
|
||||
```
|
||||
project
|
||||
- src
|
||||
- scripts
|
||||
-components
|
||||
ComponentOne.js
|
||||
ComponentTwo.js
|
||||
main.js
|
||||
- styles
|
||||
main.css
|
||||
reset.css
|
||||
index.html
|
||||
- test
|
||||
- spec
|
||||
- components
|
||||
ComponentOne.js
|
||||
ComponentTwo.js
|
||||
- helpers
|
||||
- react
|
||||
addons.js
|
||||
phantomjs-shims.js
|
||||
Gruntfile.js
|
||||
karma.conf.js
|
||||
```
|
||||
|
||||
I have tried to keep the project structure as simple as possible and understand it may not suit everyone.
|
||||
|
||||
### Naming Components
|
||||
|
||||
I have opted to follow [@floydophone](https://twitter.com/floydophone) convention of uppercase for component file naming e.g. [Component.js](https://github.com/petehunt/ReactHack/tree/master/src/components). I am open to suggestions if there is a general objection to this decision.
|
||||
|
||||
### Modules
|
||||
|
||||
Each component is a module and can be required using the [Webpack](http://webpack.github.io/) module system. [Webpack](http://webpack.github.io/) uses [Loaders](http://webpack.github.io/docs/loaders.html) which means you can also require CSS and a host of other file types. Read the [Webpack documentation](http://webpack.github.io/docs/home.html) to find out more.
|
||||
|
||||
### Grunt
|
||||
|
||||
Out the box the [Gruntfile](http://gruntjs.com/api/grunt.file) is configured with the following:
|
||||
|
||||
1. **webpack**: uses the [grunt-webpack](https://github.com/webpack/grunt-webpack) plugin to load all required modules and output to a single JS file `src/scripts/main.js`. This is included in the `src/index.html` file by default and will reload in the browser as and when it is recompiled.
|
||||
2. **watch**: uses the [grunt-watch](https://github.com/gruntjs/grunt-contrib-watch) plugin and watches for file changes. Livereload support is included by default and thus on file change the *webpack* task is run and the browser will auto update.
|
||||
3. **connect**: uses the [grunt-connect](https://github.com/gruntjs/grunt-contrib-connect) plugin to start a webserver at [localhost](http://localhost:8000).
|
||||
4. **karma**: uses the [grunt-karma](https://github.com/karma-runner/grunt-karma) plugin to load the Karma configuration file `karma.conf.js` located in the project root. This will run all tests using [PhantomJS](http://phantomjs.org/) by default but supports many other browsers.
|
||||
|
||||
### CSS
|
||||
|
||||
Included in the project is [Eric Meyer's reset.css](http://meyerweb.com/eric/tools/css/reset/) script. There is also a `src/styles/main.css` script that's required by the core `src/scripts/components/App.js` component using Webpack.
|
||||
|
||||
## Props
|
||||
|
||||
Thanks to all who contributed to [generator-angular](https://github.com/yeoman/generator-angular) as the majority of code here has been shamelessy sourced from that repos.
|
||||
|
||||
## Contribute
|
||||
|
||||
Contributions are welcomed. When submitting a bugfix, write a test that exposes the bug and fails before applying your fix. Submit the test alongside the fix.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@ -72,3 +72,7 @@ ReactWebpackGenerator.prototype.imageFiles = function () {
|
||||
this.sourceRoot(path.join(__dirname, 'templates'));
|
||||
this.directory('images', 'src/images', true);
|
||||
};
|
||||
|
||||
ReactWebpackGenerator.prototype.karmaFiles = function () {
|
||||
this.copy('../../templates/common/karma.conf.js', 'karma.conf.js');
|
||||
};
|
||||
|
||||
17
component/index.js
Normal file
17
component/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
var util = require('util');
|
||||
var ScriptBase = require('../script-base.js');
|
||||
|
||||
var ComponentGenerator = module.exports = function ComponentGenerator(args, options, config) {
|
||||
ScriptBase.apply(this, arguments);
|
||||
};
|
||||
|
||||
util.inherits(ComponentGenerator, ScriptBase);
|
||||
|
||||
ComponentGenerator.prototype.createComponentFile = function createComponentFile() {
|
||||
this.generateSourceAndTest(
|
||||
'component',
|
||||
'spec/component',
|
||||
'components'
|
||||
);
|
||||
};
|
||||
@ -14,6 +14,7 @@ var Generator = module.exports = function Generator() {
|
||||
|
||||
this.appname = this._.slugify(this._.humanize(this.appname));
|
||||
this.scriptAppName = this._.capitalize(this.appname) + generalUtils.appName(this);
|
||||
this.classedName = this._.capitalize(this.name);
|
||||
|
||||
if (typeof this.env.options.appPath === 'undefined') {
|
||||
this.env.options.appPath = this.env.options.appPath || 'src';
|
||||
@ -52,10 +53,7 @@ Generator.prototype.htmlTemplate = function (src, dest) {
|
||||
]);
|
||||
};
|
||||
|
||||
Generator.prototype.generateSourceAndTest = function (appTemplate, testTemplate, targetDirectory, skipAdd) {
|
||||
this.appTemplate(appTemplate, path.join('scripts', targetDirectory, this.name));
|
||||
this.testTemplate(testTemplate, path.join(targetDirectory, this.name));
|
||||
if (!skipAdd) {
|
||||
this.addScriptToIndex(path.join(targetDirectory, this.name));
|
||||
}
|
||||
Generator.prototype.generateSourceAndTest = function (appTemplate, testTemplate, targetDirectory) {
|
||||
this.appTemplate(appTemplate, path.join('scripts', targetDirectory, this._.capitalize(this.name)));
|
||||
this.testTemplate(testTemplate, path.join(targetDirectory, this._.capitalize(this.name)));
|
||||
};
|
||||
@ -116,7 +116,7 @@ module.exports = function (grunt) {
|
||||
}
|
||||
});
|
||||
|
||||
grunt.registerTask('server', function (target) {
|
||||
grunt.registerTask('serve', function (target) {
|
||||
if (target === 'dist') {
|
||||
return grunt.task.run(['build', 'open', 'connect:dist:keepalive']);
|
||||
}
|
||||
|
||||
58
templates/common/karma.conf.js
Normal file
58
templates/common/karma.conf.js
Normal file
@ -0,0 +1,58 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine'],
|
||||
files: [
|
||||
'test/helpers/**/*.js',
|
||||
'test/spec/components/**/*.js'
|
||||
],
|
||||
preprocessors: {
|
||||
'test/spec/components/**/*.js': ['webpack']
|
||||
},
|
||||
webpack: {
|
||||
cache: true,
|
||||
module: {
|
||||
loaders: [{
|
||||
test: /\.css$/,
|
||||
loader: 'style!css'
|
||||
}, {
|
||||
test: /\.gif/,
|
||||
loader: 'url-loader?limit=10000&minetype=image/gif'
|
||||
}, {
|
||||
test: /\.jpg/,
|
||||
loader: 'url-loader?limit=10000&minetype=image/jpg'
|
||||
}, {
|
||||
test: /\.png/,
|
||||
loader: 'url-loader?limit=10000&minetype=image/png'
|
||||
}, {
|
||||
test: /\.js$/,
|
||||
loader: 'jsx-loader'
|
||||
}]
|
||||
}
|
||||
},
|
||||
webpackServer: {
|
||||
stats: {
|
||||
colors: true
|
||||
}
|
||||
},
|
||||
exclude: [],
|
||||
port: 8080,
|
||||
logLevel: config.LOG_INFO,
|
||||
colors: true,
|
||||
autoWatch: false,
|
||||
// Start these browsers, currently available:
|
||||
// - Chrome
|
||||
// - ChromeCanary
|
||||
// - Firefox
|
||||
// - Opera
|
||||
// - Safari (only Mac)
|
||||
// - PhantomJS
|
||||
// - IE (only Windows)
|
||||
browsers: ['PhantomJS'],
|
||||
reporters: ['progress'],
|
||||
captureTimeout: 60000,
|
||||
singleRun: true
|
||||
});
|
||||
};
|
||||
21
templates/javascript/Component.js
Normal file
21
templates/javascript/Component.js
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @jsx React.DOM
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('react/addons');
|
||||
|
||||
var <%= classedName %> = React.createClass({
|
||||
/*jshint ignore:start */
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<p>Content for <%= classedName %></p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
/*jshint ignore:end */
|
||||
});
|
||||
|
||||
module.exports = <%= classedName %>;
|
||||
14
templates/javascript/spec/Component.js
Normal file
14
templates/javascript/spec/Component.js
Normal file
@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
describe('<%= classedName %>', function () {
|
||||
var <%= classedName %>, component;
|
||||
|
||||
beforeEach(function () {
|
||||
<%= classedName %> = require('../../../src/scripts/components/<%= classedName %>');
|
||||
component = <%= classedName %>();
|
||||
});
|
||||
|
||||
it('should create a new instance of <%= classedName %>', function () {
|
||||
expect(component).toBeDefined();
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user