diff --git a/README.md b/README.md index bf927f0..32d5f6f 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,7 @@ If you see the landing page, it means you have set up everything successfully. ```sh $ npm run dev # build and watch, but javascript not minified $ npm run build # build a minified production version +$ npm run build:s3 # build a minified production version, deploy it to S3 as a static app $ npm run lint # linting using ESLint $ npm run test # run test using Jest $ npm run clean # it runs before each build, so you don't need to @@ -231,7 +232,16 @@ React Redux Boilerplate supports production preview, which means that you can ru 1. Run `npm run build` and wait until it is done 2. Go to the project `docroot`, you will see a `index.html` (template is customizable, please read `Developing Template` section) -3. Open that `index.html` in your browser, and that is the build version that just got generated +3. Serve the build directory, for example like so: + +```bash +npm i -g http-server +cd docroot +http-server +``` +By default http-server will serve your production build at port 8080. Docs are [here](https://www.npmjs.com/package/http-server). + +4. Navigate to [that address](http://localhost:8080) to see your build. That's very easy, isn't it? @@ -286,23 +296,40 @@ __Note:__ If you want to add new npm target ( e.g. `npm run build:stage` ), you ### Configuring secret key/value pair -There are times you may want to put in `secret information` you don't want to check into the source code. In this boilerplate, you just need to create a file called `.env` in your `PROJECT_ROOT`, and you can put your secret over there ( we have put that into `.gitignore` just in case ). For example, in order to use the feature to deploy to S3, you need to provide the following information. +There are times you may want to put in `secret information` you don't want to check into the source code. In this boilerplate, you just need to create a file called `.env` in your `PROJECT_ROOT`, and you can put your secrets there ( we have put that into `.gitignore` just in case ). +Specifically for deployment to S3, there are two options for providing your secrets: +1. In ~/.aws/credentials, configure a block like so, for example for a profile called "default": + +```bash +[default] +AWS_ACCESS_KEY_ID=XXXXXXXX # replace with your key +AWS_SECRET_ACCESS_KEY=XXXXXXX # replace with your secret ``` -AWS_ACCESS_KEY=YOUR_AWS_ACCESS_KEY -AWS_SECRET_KEY=YOUR_AWS_SECRET_KEY -AWS_BUCKET=YOUR_AWS_BUCKET -AWS_CDN_URL=YOUR_AWS_CDN_URL +2. You can provide the same values in a `.env` file within your project: + +```bash +AWS_ACCESS_KEY_ID=YOUR_AWS_ACCESS_KEY +AWS_SECRET_ACCESS_KEY=YOUR_AWS_SECRET_KEY +``` + +If you are using the AWS CLI, chances are you already have an `~/.aws/credentials` file, so you may find option 1 simpler locally. Option 2 may be better when using a build server like Jenkins. + +Finally, no matter which of the above two options you choose, you will ALSO need to provide these additional values in your `.env` file, or otherwise set them as environment variables when you build: + +```bash +AWS_BUCKET=YOUR_AWS_BUCKET # REQUIRED for S3 deploy +AWS_CDN_URL=YOUR_AWS_CDN_URL # OPTIONAL for S3 deploy ``` -And your in node application or webpack config, those key/value pair will inject into `process.env` ( e.g. `process.env.AWS_ACCESS_KEY` ). +And your in node application or webpack config, those key/value pairs will be injected into `process.env` ( e.g. `process.env.AWS_ACCESS_KEY_ID` ). -__Note__: Using `.env` file is optional, it meant to keep secret and inject information into environment variables, if you are using Jenkin or alike type of tools, you can inject environment variables there. +__Note__: Using the `.env` file is optional, it meant to keep secret and inject information into environment variables, if you are using Jenkins or a like type of tool, you can inject environment variables there. However, with `.env`, you can create a ready to use list of environment variables for your different environment. You can even have another service to generate the `.env` file before building the project, but in terms of how to achieve that, it is out of scope of this documentation. -__Just remember__, `.env` file suppose to keep your secret, and prevent your from saving sensitive secret into source code repository \0/ !! `DO NOT` check in `.env` into your source repo !! +__Just remember__, `.env` file is supposed to keep your secret, and prevent you from saving sensitive secrets into your source code repository \0/ !! **DO NOT** check `.env` into your source repo !! We are using [dotenv](https://github.com/motdotla/dotenv) for the `.env` feature, they have pretty good documentation. @@ -434,37 +461,9 @@ And this boilerplate has a process integrated to upload artifacts ( assets.json * __How to activate S3 support ?__ - * S3 upload is optional here, but if you want to activate that, please go to your config and make `"s3Deploy": true` and fill up the `s3` config ( bucket, accessKey ... etc). Remember that you can put the same config in different environment in case you want each one has different behavior. Below is an `example` in `config/default.json` - - - ``` - ( STEP 1 ) - - // Example in config/default.json - // You can overwrite default using your other config file - // ======================================================== - // default.json - global - // development.json - development ( npm run dev ) - // release.json - test/release ( npm run build:release ) - // production.json - production ( npm run build ) - // ======================================================== - { - "s3Deploy": true, - } - ``` - - And create a `.env` file and put in the following information. Please read [Configuration](#configuration) section for more information. - - - ``` - ( STEP 2 ) - - AWS_ACCESS_KEY=blah... - AWS_SECRET_KEY=blah... - AWS_BUCKET=blah... - AWS_CDN_URL=blah... - ``` - + * S3 upload is optional here + 1. Make sure you have provided your AWS credentials to the project (secret and access key). Please read [Configuration](#configuration) section for more information. + 2. Use the `npm run build:s3` script to build and deploy. * __What is our standard to control our npm module dependencies ?__ * We are using `^version`, it means "Compatible with version". The reason we are using `^version` is simply we want the ability for us to roll back to previous working version together with the source code. @@ -472,7 +471,6 @@ And this boilerplate has a process integrated to upload artifacts ( assets.json * __How to add javascript unit test ?__ * All React JS test are under \__tests__ directory and this tool will find all the test, you don't need to do anything besides putting your test in, but please use a structure that mimic your source location that you are testing, or it will create confusion. - * __What is B.E.M style ?__ * B.E.M is short for `Block, Element, Modifier` and is a naming convention for classes in HTML and CSS. Its goal is to help developers better understand the relationship between the HTML and CSS and make our code base more maintainable. Please read the links below for getting deeper insight of it. diff --git a/config/default.json b/config/default.json index b02564e..c60d4f1 100644 --- a/config/default.json +++ b/config/default.json @@ -5,11 +5,6 @@ "publicPath": "/", "assetPath": "assets", "jsSourcePath": "src/js", - "s3": { - "s3Deploy": false, - "bucket": "if-any", - "defaultCDNBase": "if-any" - }, "optimization": { "analyzeMode": false, "analyze": { diff --git a/package.json b/package.json index c2b4832..8d1ad06 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "scripts": { "dev": "cross-env NODE_ENV=development DASHBOARD_PORT=9901 webpack-dashboard -p 9901 -c red -t dashboard -- node bin/commands.js dev", "build": "cross-env NODE_ENV=production node bin/commands.js build", + "build:s3": "cross-env S3_DEPLOY=true NODE_ENV=production node bin/commands.js build", "build:stage": "cross-env NODE_ENV=stage node bin/commands.js build", + "build:stage:s3": "cross-env S3_DEPLOY=true NODE_ENV=stage node bin/commands.js build", "clean": "rimraf docroot", "test": "jest --no-cache", "lint": "node bin/commands.js lint" diff --git a/webpack.config.build.babel.js b/webpack.config.build.babel.js index 27490d2..4f9eee9 100644 --- a/webpack.config.build.babel.js +++ b/webpack.config.build.babel.js @@ -6,20 +6,17 @@ import SaveAssetsJson from 'assets-webpack-plugin' import MiniCssExtractPlugin from 'mini-css-extract-plugin' import precss from 'precss' import postcssPresetEnv from 'postcss-preset-env' +import AWS from 'aws-sdk' + import webpackConfig, { JS_SOURCE } from './webpack.config.common' // ---------------------------------------------------------- // CONSTANT DECLARATION // ---------------------------------------------------------- - -const S3_DEPLOY = config.get('s3.s3Deploy') || 'false' -const IS_S3_DEPLOY = String(S3_DEPLOY) === 'true' - -const PUBLIC_PATH = IS_S3_DEPLOY - ? process.env.AWS_CDN_URL - : config.get('publicPath') -const APP_ENTRY_POINT = `${JS_SOURCE}/main` +const IS_S3_DEPLOY = Boolean(process.env.S3_DEPLOY); +const PUBLIC_PATH = IS_S3_DEPLOY ? process.env.AWS_CDN_URL : config.get('publicPath'); +const APP_ENTRY_POINT = `${JS_SOURCE}/main`; // webpack 4 mode // https://webpack.js.org/concepts/mode/ @@ -101,14 +98,21 @@ if (IS_S3_DEPLOY) { // Please read README if you have no idea where // `process.env.AWS_ACCESS_KEY` is coming from + let s3Options = {}; + if (process.env.AWS_PROFILE) { + s3Options = new AWS.SharedIniFileCredentials({ profile: process.env.AWS_PROFILE }); + } + if (process.env.AWS_ACCESS_KEY) { + s3Options.accessKeyId = process.env.AWS_ACCESS_KEY_ID; + } + if (process.env.AWS_SECRET_KEY) { + s3Options.secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; + } const s3Config = new S3Plugin({ // Only upload css and js // include: /.*\.(css|js)/, // s3Options are required - s3Options: { - accessKeyId: process.env.AWS_ACCESS_KEY, - secretAccessKey: process.env.AWS_SECRET_KEY, - }, + ...s3Options, s3UploadOptions: { Bucket: process.env.AWS_BUCKET, }, diff --git a/webpack.config.common.js b/webpack.config.common.js index 64ab948..a01c9e5 100644 --- a/webpack.config.common.js +++ b/webpack.config.common.js @@ -5,6 +5,11 @@ import webpack from 'webpack'; import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin'; import config from 'config'; +// Please read the following link if +// you have no idea how to use this feature +// https://github.com/motdotla/dotenv +require('dotenv').config({ silent: true }); + // trace which loader is deprecated // feel free to remove that if you don't need this feature process.traceDeprecation = false;