diff --git a/README.md b/README.md index 571d711..aeb8d3b 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ The following features are planned to be included in the final version: - [x] Mocha Unit tests (*optional*) - [x] EsLint Support - [x] No dependency on grunt, gulp or the next hot taskrunner! +- [x] The dynamic webpack configuration is clunky, there must be a better way to do that! +- [x] Karmas webpack configuration is not included in the global webpack.config.js file, but it really should ## Todo - [ ] Better performance for webpack builds -- [ ] The dynamic webpack configuration is clunky, there must be a better way to do that! -- [ ] Karmas webpack configuration is not included in the global webpack.config.js file, but it really should ## What is it for? This template can be used directly for the creation of new projects. diff --git a/cfg/base.js b/cfg/base.js new file mode 100644 index 0000000..b24bbbb --- /dev/null +++ b/cfg/base.js @@ -0,0 +1,68 @@ +var path = require('path'); + +var port = 8000; +var srcPath = path.join(__dirname, '/../src'); +var publicPath = '/assets/'; + +module.exports = { + port: port, + debug: true, + output: { + path: path.join(__dirname, '/../dist/assets'), + filename: 'app.js', + publicPath: publicPath + }, + devServer: { + contentBase: './src/', + historyApiFallback: true, + hot: true, + port: port, + publicPath: publicPath, + noInfo: false + }, + resolve: { + extensions: ['', '.js', '.jsx'], + alias: { + actions: srcPath + '/actions/', + components: srcPath + '/components/', + sources: srcPath + '/sources/', + stores: srcPath + '/stores/', + styles: srcPath + '/styles/' + } + }, + module: { + preLoaders: [ + { + test: /\.(js|jsx)$/, + include: path.join(__dirname, 'src'), + loader: 'eslint-loader' + } + ], + loaders: [ + { + test: /\.css$/, + loader: 'style!css' + }, + { + test: /\.sass/, + loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded&indentedSyntax' + }, + { + test: /\.scss/, + loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded' + }, + { + test: /\.less/, + loader: 'style-loader!css-loader!less-loader' + }, + { + test: /\.styl/, + loader: 'style-loader!css-loader!stylus-loader' + }, + { + test: /\.(png|jpg|gif|woff|woff2)$/, + loader: 'url-loader?limit=8192' + } + ] + } +}; diff --git a/cfg/dev.js b/cfg/dev.js new file mode 100644 index 0000000..6e2daec --- /dev/null +++ b/cfg/dev.js @@ -0,0 +1,28 @@ +var path = require('path'); +var webpack = require('webpack'); +var _ = require('lodash'); + +var baseConfig = require('./base'); + +var config = _.merge({ + entry: [ + 'webpack-dev-server/client?http://127.0.0.1:8000', + 'webpack/hot/only-dev-server', + './src/components/run' + ], + cache: true, + devtool: 'eval', + plugins: [ + new webpack.HotModuleReplacementPlugin(), + new webpack.NoErrorsPlugin() + ] +}, baseConfig); + +// Add needed loaders +config.module.loaders.push({ + test: /\.(js|jsx)$/, + loader: 'react-hot!babel-loader', + include: path.join(__dirname, '/../src') +}); + +module.exports = config; diff --git a/cfg/dist.js b/cfg/dist.js new file mode 100644 index 0000000..d2eb6dd --- /dev/null +++ b/cfg/dist.js @@ -0,0 +1,26 @@ +var path = require('path'); +var webpack = require('webpack'); +var _ = require('lodash'); + +var baseConfig = require('./base'); + +var config = _.merge({ + entry: path.join(__dirname, '../src/components/run'), + cache: false, + devtool: 'sourcemap', + plugins: [ + new webpack.optimize.DedupePlugin(), + new webpack.optimize.UglifyJsPlugin(), + new webpack.optimize.OccurenceOrderPlugin(), + new webpack.optimize.AggressiveMergingPlugin(), + new webpack.NoErrorsPlugin() + ] +}, baseConfig); + +config.module.loaders.push({ + test: /\.(js|jsx)$/, + loader: 'babel', + include: path.join(__dirname, '/../src') +}); + +module.exports = config; diff --git a/cfg/test.js b/cfg/test.js new file mode 100644 index 0000000..e4682e8 --- /dev/null +++ b/cfg/test.js @@ -0,0 +1,33 @@ +var path = require('path'); +var srcPath = path.join(__dirname, '/../src/'); + +module.exports = { + devtool: 'eval', + module: { + loaders: [ + { + test: /\.(png|jpg|gif|woff|woff2|css|sass|scss|less|styl)$/, + loader: 'null-loader' + }, + { + test: /\.(js|jsx)$/, + loader: 'babel-loader', + include: [ + path.join(__dirname, '/../src'), + path.join(__dirname, '/../test') + ] + } + ] + }, + resolve: { + extensions: ['', '.js', '.jsx'], + alias: { + actions: srcPath + 'actions/', + helpers: path.join(__dirname, '/../test/helpers'), + components: srcPath + 'components/', + sources: srcPath + 'sources/', + stores: srcPath + 'stores/', + styles: srcPath + 'styles/' + } + } +}; diff --git a/dist/assets/42092f929161dae9c08a21bfb46ece4d.png b/dist/assets/42092f929161dae9c08a21bfb46ece4d.png new file mode 100644 index 0000000..92497ad Binary files /dev/null and b/dist/assets/42092f929161dae9c08a21bfb46ece4d.png differ diff --git a/karma.conf.js b/karma.conf.js index 6e7c921..65b452a 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,5 +1,4 @@ -var path = require('path'); -var srcPath = __dirname + '/src/'; +var webpackCfg = require('./webpack.config'); module.exports = function(config) { config.set({ @@ -12,46 +11,14 @@ module.exports = function(config) { captureTimeout: 60000, frameworks: ['phantomjs-shim', 'mocha', 'chai'], client: { - mocha: { - - } + mocha: {} }, singleRun: true, reporters: ['mocha'], preprocessors: { 'test/loadtests.js': ['webpack', 'sourcemap'] }, - webpack: { - cache: true, - devtool: 'eval', - module: { - loaders: [ - { - test: /\.(png|jpg|gif|woff|woff2|css|sass|scss|less|styl)$/, - loader: 'null-loader' - }, - { - test: /\.(js|jsx)$/, - loader: 'babel-loader', - include: [ - path.join(__dirname, 'src'), - path.join(__dirname, 'test') - ] - } - ] - }, - resolve: { - extensions: ['', '.js', '.jsx'], - alias: { - actions: srcPath + '/actions/', - helpers: path.join(__dirname, 'test', 'helpers'), - components: srcPath + '/components/', - sources: srcPath + '/sources/', - stores: srcPath + '/stores/', - styles: srcPath + '/styles/' - } - } - }, + webpack: webpackCfg, webpackServer: { noInfo: true } diff --git a/package.json b/package.json index 8d87698..a95d807 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "react-webpack-template", "version": "0.0.10", "description": "A base skeleton template for react and webpack without task runners", - "main": "index.js", + "main": "server.js", "scripts": { "start": "node server.js --env=dev", "test": "karma start", @@ -13,7 +13,9 @@ "lint": "eslint ./src", "copy": "copyfiles -f ./src/index.html ./src/favicon.ico ./dist", "clean": "rimraf dist/*", - "patch-release": "npm version patch && npm publish && git push --follow-tags" + "release:major": "npm version major && npm publish && git push --follow-tags", + "release:minor": "npm version minor && npm publish && git push --follow-tags", + "release:patch": "npm version patch && npm publish && git push --follow-tags" }, "repository": { "type": "git", @@ -63,6 +65,7 @@ "webpack-dev-server": "^1.10.1" }, "dependencies": { + "lodash": "^3.10.1", "normalize.css": "^3.0.3", "react": "^0.13.3" } diff --git a/test/components/MainTest.js b/test/components/MainTest.js index 0a1c498..747f049 100644 --- a/test/components/MainTest.js +++ b/test/components/MainTest.js @@ -20,8 +20,4 @@ describe('MainComponent', () => { it('should have its component name as default className', () => { expect(MainComponent._store.props.className).to.equal('index'); }); - - it('should do something!', () => { - expect(true).to.be.true; - }); }); diff --git a/webpack.config.js b/webpack.config.js index 965d4f0..b7882b0 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,116 +1,47 @@ -var webpack = require('webpack'); -var args = require('minimist')(process.argv.slice(2)); +'use strict'; + var path = require('path'); -var env = args.env || 'dev'; +var args = require('minimist')(process.argv.slice(2)); -var port = 8000; -var srcPath = __dirname + '/src/'; -var publicPath = '/assets/'; +// List of allowed environments +var allowedEnvs = ['dev', 'dist', 'test']; -var config = { - port: port, - debug: true, - output: { - path: path.join(__dirname, 'dist/assets'), - filename: 'app.js', - publicPath: publicPath - }, - devServer: { - contentBase: './src/', - historyApiFallback: true, - hot: true, - port: port, - publicPath: publicPath, - noInfo: false - }, - resolve: { - extensions: ['', '.js', '.jsx'], - alias: { - actions: srcPath + '/actions/', - components: srcPath + '/components/', - sources: srcPath + '/sources/', - stores: srcPath + '/stores/', - styles: srcPath + '/styles/' - } - }, - module: { - preLoaders: [ - { - test: /\.(js|jsx)$/, - include: path.join(__dirname, 'src'), - loader: 'eslint-loader' - } - ], - loaders: [ - { - test: /\.css$/, - loader: 'style!css' - }, - { - test: /\.sass/, - loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded&indentedSyntax' - }, - { - test: /\.scss/, - loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded' - }, - { - test: /\.less/, - loader: 'style-loader!css-loader!less-loader' - }, - { - test: /\.styl/, - loader: 'style-loader!css-loader!stylus-loader' - }, - { - test: /\.(png|jpg|gif|woff|woff2)$/, - loader: 'url-loader?limit=8192' - } - ] - } -}; - -// Use config depending on environment -switch(env) { - case 'dist': - config.entry = './src/components/run'; - config.cache = false; - config.devtool = 'sourcemap'; - config.plugins = [ - new webpack.optimize.DedupePlugin(), - new webpack.optimize.UglifyJsPlugin(), - new webpack.optimize.OccurenceOrderPlugin(), - new webpack.optimize.AggressiveMergingPlugin(), - new webpack.NoErrorsPlugin() - ]; - - // Add needed loaders - config.module.loaders.push({ - test: /\.(js|jsx)$/, - loader: 'babel', - include: path.join(__dirname, 'src') - }); - break; - - default: - config.entry = [ - 'webpack-dev-server/client?http://127.0.0.1:' + port, - 'webpack/hot/only-dev-server', - './src/components/run' - ]; - config.cache = true; - config.devtool = 'eval'; - config.plugins = [ - new webpack.HotModuleReplacementPlugin(), - new webpack.NoErrorsPlugin() - ]; - - // Add needed loaders - config.module.loaders.push({ - test: /\.(js|jsx)$/, - loader: 'react-hot!babel-loader', - include: path.join(__dirname, 'src') - }); +// Set the correct environment +var env; +if(args._.length > 0 && args._.indexOf('start') !== -1) { + env = 'test'; +} else if (args.env) { + env = args.env; +} else { + env = 'dev'; } -module.exports = config; +// Get available configurations +var configs = { + base: require(path.join(__dirname, 'cfg/base')), + dev: require(path.join(__dirname, 'cfg/dev')), + dist: require(path.join(__dirname, 'cfg/dist')), + test: require(path.join(__dirname, 'cfg/test')) +}; + +/** + * Get an allowed environment + * @param {String} env + * @return {String} + */ +function getValidEnv(env) { + var isValid = env && env.length > 0 && allowedEnvs.indexOf(env) !== -1; + return isValid ? env : 'dev'; +} + +/** + * Build the webpack configuration + * @param {String} env Environment to use + * @return {Object} Webpack config + */ +function buildConfig(env) { + var usedEnv = getValidEnv(env); + return configs[usedEnv]; +} + +module.exports = buildConfig(env);