diff --git a/README.md b/README.md index c6e1f2b4..411c8eb4 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,13 @@ # AccurApp This is a project kickstarter for the specific needs of Accurat. It was originally forked from [create-react-app](https://github.com/facebookincubator/create-react-app/), -but in version 3.0.0 significant amounts of code were rewritten and simplified. +but in version 3.0.0 significant amounts of code were rewritten and simplified. Here are some added features: -## Getting started: +- ESLint config is the one configured for Accurat, `eslint-config-accurapp`, based on StandardJS with some customizations +- Babel presets are `stage-0` and `latest` with decorators support +- GLSL webpack loader, to import shaders and require shaders within shaders + +## Creating a new project: Having installed yarn (`brew install yarn`), run this command which will handle the folder scaffolding, the dependencies installation, and the git initialization with a first commit. ```sh yarn create accurapp project-name @@ -11,22 +15,46 @@ yarn create accurapp project-name Then you just `cd project-name`, run `yarn start` and start creating awesome stuff! 🎉 -## Setting up bitbucket +#### Setting up bitbucket 1. Create a new repo 1. Choose `I have an existing project` and follow the instructions -## Setting up the automatic deploy +#### Setting up the automatic deploy 1. Go into `Settings > Pipelines - Settings` and enable Bitbucket Pipelines 1. Go into `Settings > Pipelines - Environment Variables` and add the environment variables `DEPLOY_CUSTOMER`, `DEPLOY_PROJECT`, `SLACK_CHANNEL` -## Original documentation: -- [Getting Started](https://github.com/facebookincubator/create-react-app/#getting-started) -- [User Guide](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md) +## Usage +These are the available commands once you created a project: +- `yarn start` starts a server locally, accessible both from your browser and from another machine using your same wi-fi +- `yarn build` builds the project for production, ready to be deployed from the `build/` folder -## Features: -- ESLint config is the one configured for Accurat, `eslint-config-accurapp`, based on StandardJS with some customizations -- Babel presets are `stage-0` and `latest` with decorators support -- GLSL webpack loader, to import shaders and require shaders within shaders +#### Customizing Webpack +You can pass the custom webpack config to the `buildWebpackConfig` function in the project's `webpack.config.js`. +```js +const buildWebpackConfig = require('webpack-preset-accurapp') + +module.exports = buildWebpackConfig({ + target: 'node', +}) +``` + +Or to make your life easier, you could also use [webpack-blocks](https://github.com/andywer/webpack-blocks/tree/release/1.0), it's a nice level of abstraction over the webpack configuration, you can add loaders, plugins, configuration with just one line. +```js +const buildWebpackConfig = require('webpack-preset-accurapp') +const { sass } = require('webpack-blocks') + +module.exports = buildWebpackConfig([ + sass(), +]) +``` + +#### Customizing Babel +```js +// TODO do a babel-preset-accurapp if we need to customize babel +``` + +#### Customizing Eslint +Add your custom rules to the `.eslintrc` ## Project Scaffolding ``` @@ -50,40 +78,13 @@ Then you just `cd project-name`, run `yarn start` and start creating awesome stu └── yarn.lock ``` -## Customizing Webpack -Edit the `webpack.config.js` and add new [webpack-blocks](https://github.com/andywer/webpack-blocks), to see how to create custom blocks, add plugins, add loaders, check out their [docs](https://github.com/andywer/webpack-blocks). -```js -const buildWebpackConfig = require('webpack-preset-accurapp') -const sass = require('@webpack-blocks/sass') - -module.exports = buildWebpackConfig([ - sass(), -]) -``` - -## Customizing Babel -Create a `.babelrc` and pass it to `buildWebpackConfig` in the second arguments, which is an object of overrides -```js -// .babelrc -{ - "presets": ["latest"], - "plugins": ["fast-async"] -} - -// webpack.config.js -const buildWebpackConfig = require('webpack-preset-accurapp') - -module.exports = buildWebpackConfig([], { - babel: { babelrc: true }, -}) -``` - -## Customizing Eslint -Add your custom rules to the `.eslintrc` - ## Contributing If you make some edits and wish to test them locally you can run `yarn create-test-app` which creates a test app using the local packages. +## Original documentation: +- [Getting Started](https://github.com/facebookincubator/create-react-app/#getting-started) +- [User Guide](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md) + ## TODOs - use CommonsChunkPlugin for faster build times? - do more beautiful console output like zeppelin does diff --git a/packages/accurapp-scripts/package.json b/packages/accurapp-scripts/package.json index 6440d568..92d937bd 100644 --- a/packages/accurapp-scripts/package.json +++ b/packages/accurapp-scripts/package.json @@ -15,19 +15,19 @@ "accurapp-scripts": "./bin/scripts.js" }, "dependencies": { - "boxen": "^1.1.0", - "chalk": "^2.0.1", + "boxen": "^1.2.1", + "chalk": "^2.1.0", "cross-spawn": "^5.1.0", "detect-port": "^1.2.0", "dotenv": "^4.0.0", "figlet": "^1.2.0", - "fs-extra": "^3.0.1", + "fs-extra": "^4.0.1", "latest-version": "^3.1.0", "path": "^0.12.7", - "react-dev-utils": "^3.0.2", - "semver": "^5.3.0", - "webpack": "^2.6.1", - "webpack-dev-server": "^2.4.5" + "react-dev-utils": "^4.0.1", + "semver": "^5.4.1", + "webpack": "^3.5.6", + "webpack-dev-server": "^2.7.1" }, "devDependencies": {} } diff --git a/packages/accurapp-scripts/scripts/build.js b/packages/accurapp-scripts/scripts/build.js index b008b40f..15aa0c00 100644 --- a/packages/accurapp-scripts/scripts/build.js +++ b/packages/accurapp-scripts/scripts/build.js @@ -7,7 +7,7 @@ const chalk = require('chalk') const path = require('path') const fs = require('fs-extra') const { measureFileSizesBeforeBuild, printFileSizesAfterBuild } = require('react-dev-utils/FileSizeReporter') -const { log, createWebpackCompiler, readWebpackConfig, coloredBanner } = require('./_utils') +const { log, createWebpackCompiler, readWebpackConfig, coloredBanner } = require('./_utils') const appDir = process.cwd() const config = readWebpackConfig() diff --git a/packages/webpack-preset-accurapp/customBlocks.js b/packages/webpack-preset-accurapp/customBlocks.js index beced53f..de4c3f2a 100644 --- a/packages/webpack-preset-accurapp/customBlocks.js +++ b/packages/webpack-preset-accurapp/customBlocks.js @@ -1,10 +1,42 @@ +const fileNameTemplate = '[name].[hash:8].[ext]' + /** - * You will be able to import starting from the src folder so you don't have to ../../../ + * Images smaller than 10kb are loaded as a base64 encoded url instead of file url */ -function resolveSrc() { - return () => ({ - resolve: { - modules: ['node_modules', 'src'], +function imageLoader() { + return (context, { addLoader }) => addLoader({ + test: /\.(gif|ico|jpg|jpeg|png|webp)$/, + loader: 'url-loader', + options: { + limit: 10000, + name: fileNameTemplate, + }, + }) +} + +/** + * Videos smaller than 10kb are loaded as a base64 encoded url instead of file url + */ +function videoLoader() { + return (context, { addLoader }) => addLoader({ + test: /\.(mp4|webm)$/, + loader: 'url-loader', + options: { + limit: 10000, + name: fileNameTemplate, + }, + }) +} + +/** + * Fonts are loaded as file urls + */ +function fontLoader() { + return (context, { addLoader }) => addLoader({ + test: /\.(eot|ttf|woff|woff2)(\?.*)?$/, + loader: 'file-loader', + options: { + name: fileNameTemplate, }, }) } @@ -14,15 +46,9 @@ function resolveSrc() { * allowing you to install GLSL modules from npm and use them in your shaders. */ function glslifyLoader() { - return () => ({ - module: { - loaders: [ // TODO change this in rules when webpack-blocks 1.0 is out - { - test: /\.(glsl|frag|vert)$/, - loaders: ['raw-loader', 'glslify-loader'], - }, - ], - }, + return (context, { addLoader }) => addLoader({ + test: /\.(glsl|frag|vert)$/, + use: ['raw-loader', 'glslify-loader'], }) } @@ -30,15 +56,22 @@ function glslifyLoader() { * Run ESLint on every required file. */ function eslintLoader() { - return () => ({ - module: { - loaders: [{ - test: /\.(js|jsx)$/, - enforce: 'pre', // It's important to do this before Babel processes the JS. - exclude: [/node_modules/], - loader: 'eslint-loader', - options: { useEslintrc: true }, - }], + return (context, { addLoader }) => addLoader({ + test: /\.(js|jsx)$/, + enforce: 'pre', // It's important to do this before Babel processes the JS. + exclude: /node_modules/, + loader: 'eslint-loader', + options: { useEslintrc: true }, + }) +} + +/** + * You will be able to import starting from the src folder so you don't have to ../../../ + */ +function resolveSrc() { + return (context, { merge }) => merge({ + resolve: { + modules: ['node_modules', 'src'], }, }) } @@ -47,21 +80,28 @@ function eslintLoader() { * Add entryPoint at beginning of 'entry' array */ function prependEntry(entry) { - const blockFunction = (context, config) => { + const blockFunction = (context, util) => { if (!context.entriesToPrepend) context.entriesToPrepend = [] context.entriesToPrepend.unshift(entry) + return config => config } return Object.assign(blockFunction, { post: prependEntryPostHook, }) } -function prependEntryPostHook(context, config) { - config.entry.main.unshift(...context.entriesToPrepend) +function prependEntryPostHook(context, util) { + return (config) => { + config.entry.main.unshift(...context.entriesToPrepend) + return config + } } module.exports = { - resolveSrc, + imageLoader, + videoLoader, + fontLoader, glslifyLoader, eslintLoader, + resolveSrc, prependEntry, } diff --git a/packages/webpack-preset-accurapp/index.js b/packages/webpack-preset-accurapp/index.js index f648008c..6cdc9096 100644 --- a/packages/webpack-preset-accurapp/index.js +++ b/packages/webpack-preset-accurapp/index.js @@ -1,6 +1,17 @@ -const { addPlugins, createConfig, customConfig, env, entryPoint, setOutput, sourceMaps, webpack } = require('@webpack-blocks/webpack2') -const babelLoader = require('@webpack-blocks/babel6') -const postcss = require('@webpack-blocks/postcss') +const webpack = require('webpack') +const { + createConfig, + addPlugins, + customConfig, + entryPoint, + setOutput, + env, + performance, + sourceMaps, + babel, + postcss, +} = require('webpack-blocks') +const { css } = require('@webpack-blocks/assets') const autoprefixer = require('autoprefixer') const path = require('path') @@ -8,17 +19,24 @@ const HtmlWebpackPlugin = require('html-webpack-plugin') const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin') const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin') const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin') +const NpmInstallPlugin = require('npm-install-webpack-plugin') const MinifyPlugin = require('babel-minify-webpack-plugin') -const { resolveSrc, glslifyLoader, eslintLoader, prependEntry } = require('./customBlocks') +const { + imageLoader, + videoLoader, + fontLoader, + glslifyLoader, + eslintLoader, + resolveSrc, + prependEntry, +} = require('./customBlocks') // TODO move browsers in package.json when they will be supported https://github.com/babel/babel-preset-env/issues/149 const browsers = process.env.NODE_ENV === 'development' ? ['last 1 Chrome version'] : ['last 2 versions', 'ie 10'] const babelrc = require('./babelrc')(browsers) -// TODO understand how to customize file-loader in webpack-blocks to set the output asset name line create-react-app does instead of only hash: '[name].[hash:8].[ext]' https://github.com/andywer/webpack-blocks/issues/145 - -function accuPreset(blocks = [], overrides = {}) { +function accuPreset(config = []) { return createConfig([ entryPoint([ // Include all polyfills we can, to prevent cross-browser bugs. @@ -31,9 +49,16 @@ function accuPreset(blocks = [], overrides = {}) { filename: 'app.js', publicPath: '/', }), - resolveSrc(), + + // Loaders + css(), + babel(babelrc), + fontLoader(), + imageLoader(), + videoLoader(), glslifyLoader(), - babelLoader(overrides.babel || babelrc), + + resolveSrc(), addPlugins([ // Makes some environment variables available to the JS code @@ -53,6 +78,9 @@ function accuPreset(blocks = [], overrides = {}) { }), // Check case of paths, so case-sensitive filesystems won't complain: new CaseSensitivePathsPlugin(), + // Concatenate the scope of all module in a single closure, + // so the compiled code is a bit smaller and gets executed a bit faster + new webpack.optimize.ModuleConcatenationPlugin(), ]), // @@ -73,15 +101,13 @@ function accuPreset(blocks = [], overrides = {}) { new webpack.HotModuleReplacementPlugin(), // Automatic rediscover of packages after `npm install` new WatchMissingNodeModulesPlugin('node_modules'), + // Automatically install dependencies when you type `import ...` in your editor + new NpmInstallPlugin(), ]), // Faster 'cheap-module-eval-source-map' instead of the standard 'cheap-module-source-map' sourceMaps('cheap-module-eval-source-map'), - customConfig({ - // Turn off performance hints during development - performance: { - hints: false, - }, - }), + // Turn off performance hints during development + performance({ hints: false }), ]), // @@ -124,7 +150,7 @@ function accuPreset(blocks = [], overrides = {}) { ]), ]), - ...blocks, + ...(Array.isArray(config) ? config : [customConfig(config)]), ]) } diff --git a/packages/webpack-preset-accurapp/package.json b/packages/webpack-preset-accurapp/package.json index 195cc636..49cd1580 100644 --- a/packages/webpack-preset-accurapp/package.json +++ b/packages/webpack-preset-accurapp/package.json @@ -12,22 +12,25 @@ "webpack-blocks" ], "dependencies": { - "@webpack-blocks/babel6": "^0.4.1", - "@webpack-blocks/postcss": "^0.4.3", - "@webpack-blocks/webpack2": "^0.4.0", - "autoprefixer": "^7.1.1", + "@webpack-blocks/assets": "^1.0.0-alpha", + "autoprefixer": "^7.1.4", "babel-minify-webpack-plugin": "^0.2.0", "babel-plugin-lodash": "^3.2.11", "babel-plugin-transform-decorators-legacy": "^1.3.4", - "babel-polyfill": "^6.23.0", - "babel-preset-env": "^1.5.2", + "babel-polyfill": "^6.26.0", + "babel-preset-env": "^1.6.0", "babel-preset-react": "^6.24.1", "babel-preset-stage-0": "^6.24.1", "case-sensitive-paths-webpack-plugin": "^2.1.1", - "eslint-loader": "^1.7.1", + "eslint-loader": "^1.9.0", + "file-loader": "^0.11.2", "glslify-loader": "^1.0.2", - "html-webpack-plugin": "^2.28.0", + "html-webpack-plugin": "^2.30.1", + "npm-install-webpack-plugin": "^4.0.5", "raw-loader": "^0.5.1", - "react-dev-utils": "^3.0.0" + "react-dev-utils": "^4.0.1", + "url-loader": "^0.5.9", + "webpack": "^3.5.6", + "webpack-blocks": "^1.0.0-beta.4" } }