diff --git a/Gruntfile.js b/Gruntfile.js index 9b5ab45..e2d7912 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,14 +1,5 @@ 'use strict'; -var serveStatic = require('serve-static'); - -var mountFolder = function (dir) { - return serveStatic(require('path').resolve(dir)); -}; - -var webpackDistConfig = require('./webpack.dist.config.js'); -var webpackDevConfig = require('./webpack.config.js'); - module.exports = function (grunt) { // Let *load-grunt-tasks* require everything require('load-grunt-tasks')(grunt); @@ -19,107 +10,24 @@ module.exports = function (grunt) { grunt.initConfig({ 'pkg': pkgConfig, - 'webpack': { - options: webpackDistConfig, - dist: { - cache: false - } - }, - - 'webpack-dev-server': { - options: { - hot: true, - port: 8000, - webpack: webpackDevConfig, - publicPath: '/assets/', - contentBase: './<%= pkg.src %>/' - }, - - start: { - keepAlive: true - } - }, - - 'connect': { - options: { - port: 8000 - }, - - dist: { - options: { - keepalive: true, - middleware: function () { - return [ - mountFolder(pkgConfig.dist) - ]; - } - } - } - }, - 'open': { options: { delay: 500 }, - dev: { - path: 'http://localhost:<%= connect.options.port %>/webpack-dev-server/index.web.html' - }, dist: { - path: 'http://localhost:<%= connect.options.port %>/index.html' - } - }, - - 'karma': { - unit: { - configFile: 'karma.conf.js' - } - }, - - 'copy': { - dist: { - files: [ - { - flatten: true, - src: ['<%= pkg.src %>/index.web.html'], - dest: '<%= pkg.dist %>/index.html' - }, - { - flatten: true, - src: ['<%= pkg.src %>/favicon.ico'], - dest: '<%= pkg.dist %>/favicon.ico' - } - ] - } - }, - - 'clean': { - dist: { - files: [{ - dot: true, - src: [ - '<%= pkg.dist %>' - ] - }] - } - }, - - 'watch': { - options: { - livereload: true - }, - build: { - files: 'src/**/*.js', - tasks: ['webpack'] + path: 'http://localhost:8000/' } }, 'exec': { - launch_nw: '/Applications/nwjs.app/Contents/MacOS/nwjs .' + watch: pkgConfig.scripts.watch, + server: pkgConfig.scripts.server, + launch_nw: '/Applications/nwjs.app/Contents/MacOS/nwjs dist' }, 'concurrent': { target: { - tasks: ['watch', 'exec:launch_nw'], + tasks: ['exec:watch', 'exec:launch_nw'], options: { logConcurrentOutput: true } @@ -128,13 +36,9 @@ module.exports = function (grunt) { }); grunt.registerTask('serve-web', function (target) { - if (target === 'dist') { - return grunt.task.run(['build', 'open:dist', 'connect:dist']); - } - grunt.task.run([ - 'open:dev', - 'webpack-dev-server' + 'open:dist', + 'exec:server' ]); }); @@ -144,7 +48,5 @@ module.exports = function (grunt) { ]); }); - grunt.registerTask('test', ['karma']); - grunt.registerTask('build', ['clean', 'copy', 'webpack']); grunt.registerTask('default', []); }; diff --git a/README.md b/README.md index 651b5a5..1e071bb 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,8 @@ This project uses libraries and tools like: - [NW](http://nwjs.io) to package the Desktop App - [flux](https://facebook.github.io/flux) to organize the data flow management - [css-loader](https://github.com/webpack/css-loader) to integrate the styles in the builds -- [grunt](http://gruntjs.com) to create the builds -- [webpack](https://webpack.github.io) to help during the development phase with hot reloading +- [grunt](http://gruntjs.com) to launch NW.js or your web browser +- [webpack](https://webpack.github.io) to create the builds and help during the development phase with hot reloading ## Basic philosophy @@ -148,8 +148,8 @@ There isn't any addtional requirements since you already installed the deps with ### Quick start -- `npm run build` to build the project (at least the first time) -- `npm run serve-web` to preview in the browser at http://localhost:8000/index.web.html or http://localhost:8000/webpack-dev-server/index.web.html with webpack-dev-server and hot reload enabled +- `npm run build` to build the project +- `npm run serve-web` to preview in the browser at http://localhost:8000/ with webpack-dev-server and hot reload enabled Congratulations! You've just successfully run the project as a Website App. @@ -171,7 +171,7 @@ You can also setup an alias to call the binary. ### Quick start -- `npm run build` to build the project (at least the first time) +- `npm run build` to build the project - `npm run serve-nw` to launch the desktop app and enable livereload Congratulations! You've just successfully run the project as a Desktop App. diff --git a/index.web.html b/index.html similarity index 50% rename from index.web.html rename to index.html index 84cbeee..609c401 100644 --- a/index.web.html +++ b/index.html @@ -1,8 +1,14 @@ - + - Calculator Web App + {%=o.htmlWebpackPlugin.options.title || 'Webpack App'%} + {% if (o.htmlWebpackPlugin.files.favicon) { %} + + {% } %} + {% for (var css in o.htmlWebpackPlugin.files.css) { %} + + {% } %} @@ -16,6 +22,9 @@ - + + {% for (var chunk in o.htmlWebpackPlugin.files.chunks) { %} + + {% } %} diff --git a/index.nw.html b/index.nw.html deleted file mode 100644 index 4ec0975..0000000 --- a/index.nw.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Calculator Desktop App - - -
- - - - - diff --git a/karma.conf.js b/karma.conf.js index ae1d042..f868a67 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,6 +1,6 @@ 'use strict'; -var path = require('path'); +var webpackConfig = require('./webpack.config.js'); module.exports = function (config) { config.set({ @@ -19,27 +19,7 @@ module.exports = function (config) { }, webpack: { cache: true, - module: { - loaders: [{ - test: /\.gif/, - loader: 'url-loader?limit=10000&mimetype=image/gif' - }, { - test: /\.jpg/, - loader: 'url-loader?limit=10000&mimetype=image/jpg' - }, { - test: /\.png/, - loader: 'url-loader?limit=10000&mimetype=image/png' - }, { - test: /\.js$/, - loader: 'babel-loader' - }, { - test: /\.sass/, - loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded' - }, { - test: /\.css$/, - loader: 'style-loader!css-loader' - }] - } + module: webpackConfig.module }, webpackServer: { stats: { diff --git a/package.json b/package.json index 5ecf63c..20a7ef1 100644 --- a/package.json +++ b/package.json @@ -16,15 +16,12 @@ "flux", "babel" ], - "src": "./", - "test": "./test", - "dist": "./dist", - "mainInput": "main", - "mainOutput": "main", - "main": "index.nw.html", "scripts": { - "build": "grunt build", + "build": "npm run clean && `npm bin`/webpack --config webpack.dist.config.js", + "clean": "`npm bin`/rimraf dist", "deploy": "gh-pages -d dist", + "karma": "`npm bin`/karma start", + "server": "`npm bin`/webpack-dev-server --config ./webpack.hot.config.js --content-base ./dist/ --port 8000 --inline --hot --progress", "travis": "npm run build && npm run react-native:ios && npm run react-native:android && npm test", "react-native:ios": "react-native bundle --root src --platform ios --minify", "react-native:android": "react-native bundle --root src --platform android --minify", @@ -32,14 +29,8 @@ "serve-web": "grunt serve-web", "serve-web:dist": "grunt serve-web:dist", "start": "node_modules/react-native/packager/packager.sh", - "test": "jest" - }, - "window": { - "toolbar": true, - "min_width": 300, - "min_height": 475, - "max_width": 800, - "max_height": 600 + "test": "`npm bin`/jest", + "watch": "`npm bin`/webpack --config webpack.config.js --watch" }, "jest": { "scriptPreprocessor": "/node_modules/babel-jest", @@ -80,20 +71,15 @@ "css-loader": "^0.22.0", "eslint": "^1.9.0", "eslint-plugin-react": "^3.8.0", + "file-loader": "^0.8.4", "gh-pages": "^0.5.0", "grunt": "^0.4.5", "grunt-concurrent": "^2.0.4", - "grunt-contrib-clean": "^0.6.0", - "grunt-contrib-connect": "^0.11.2", - "grunt-contrib-copy": "^0.8.2", - "grunt-contrib-watch": "^0.6.1", "grunt-exec": "^0.4.6", - "grunt-karma": "^0.12.1", "grunt-open": "^0.2.3", - "grunt-webpack": "^1.0.11", + "html-webpack-plugin": "^1.6.2", + "jasmine-core": "^2.3.4", "jest-cli": "^0.7.1", - "jshint": "^2.8.0", - "jshint-loader": "^0.8.3", "karma": "^0.13.15", "karma-chrome-launcher": "^0.2.1", "karma-firefox-launcher": "^0.1.6", @@ -102,7 +88,10 @@ "karma-script-launcher": "^0.1.0", "karma-webpack": "^1.7.0", "load-grunt-tasks": "^3.3.0", + "node-sass": "^3.4.1", + "phantomjs": "^1.9.18", "react-hot-loader": "^1.3.0", + "rimraf": "^2.4.3", "sass-loader": "^3.1.1", "style-loader": "^0.13.0", "url-loader": "^0.5.6", diff --git a/src/index.js b/src/index.js index 05ca008..c116947 100644 --- a/src/index.js +++ b/src/index.js @@ -5,6 +5,9 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { Router, Route } from 'react-router'; +require('file?name=package.json!./package.web.json'); +require('file?name=favicon.ico!../favicon.ico'); + // CSS require('normalize.css'); require('./styles/main.css'); diff --git a/src/package.web.json b/src/package.web.json new file mode 100644 index 0000000..21ea46e --- /dev/null +++ b/src/package.web.json @@ -0,0 +1,11 @@ +{ + "name": "react-native-nw-react-calculator-nwjs", + "main": "index.html", + "window": { + "toolbar": true, + "min_width": 300, + "min_height": 475, + "max_width": 800, + "max_height": 600 + } +} diff --git a/webpack.config.js b/webpack.config.js index 8a20ea3..ac1cb3f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,36 +1,41 @@ /* - * Webpack development server configuration + * Webpack base configuration */ 'use strict'; -var webpack = require('webpack'); +var path = require('path'); +var HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { - output: { - filename: 'main.js', - publicPath: '/assets/' - }, - cache: true, - debug: true, - devtool: false, + devtool: 'source-map', + entry: [ - 'webpack/hot/only-dev-server', - './src/index.js' + './src/index.js' ], + + output: { + filename: 'assets/main.js', + path: path.join(__dirname, 'dist') + }, + stats: { colors: true, reasons: true }, + plugins: [ - new webpack.HotModuleReplacementPlugin(), - new webpack.NoErrorsPlugin() + new HtmlWebpackPlugin({ + title: 'Calculator App', + template: './index.html' + }) ], + module: { loaders: [{ test: /\.js$/, exclude: /node_modules/, - loader: 'react-hot!babel-loader' + loader: 'babel-loader' }, { test: /\.sass/, loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded&indentedSyntax' diff --git a/webpack.dist.config.js b/webpack.dist.config.js index a65c7fe..4e02671 100644 --- a/webpack.dist.config.js +++ b/webpack.dist.config.js @@ -6,41 +6,17 @@ 'use strict'; +require('babel/register'); var webpack = require('webpack'); +var baseConfig = require('./webpack.config.js'); -module.exports = { - output: { - publicPath: '/assets/', - path: 'dist/assets/', - filename: 'main.js' - }, - debug: false, +module.exports = Object.assign({}, baseConfig, { devtool: false, - entry: './src/index.js', - stats: { - colors: true, - reasons: false - }, - plugins: [ + + plugins: baseConfig.plugins.concat([ new webpack.optimize.DedupePlugin(), new webpack.optimize.UglifyJsPlugin(), new webpack.optimize.OccurenceOrderPlugin(), new webpack.optimize.AggressiveMergingPlugin() - ], - module: { - loaders: [{ - test: /\.js$/, - exclude: /node_modules/, - loader: 'babel-loader' - }, { - test: /\.css$/, - loader: 'style-loader!css-loader' - }, { - test: /\.sass/, - loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded&indentedSyntax' - }, { - test: /\.(png|jpg)$/, - loader: 'url-loader?limit=8192' - }] - } -}; + ]) +}); diff --git a/webpack.hot.config.js b/webpack.hot.config.js new file mode 100644 index 0000000..cbf4e8a --- /dev/null +++ b/webpack.hot.config.js @@ -0,0 +1,24 @@ +/* + * Webpack development server configuration + */ + +'use strict'; + +require('babel/register'); +var webpack = require('webpack'); +var baseConfig = require('./webpack.config.js'); + +module.exports = Object.assign({}, baseConfig, { + debug: true, + + entry: [ + 'webpack/hot/only-dev-server' + ].concat(baseConfig.entry), + + plugins: baseConfig.plugins.concat([ + new webpack.HotModuleReplacementPlugin(), + new webpack.NoErrorsPlugin() + ]) +}); + +module.exports.module.loaders[0].loader = 'react-hot!babel-loader';