From b98332d9e5c3993ba4fadbe408c38592993852f3 Mon Sep 17 00:00:00 2001 From: alok Date: Fri, 2 Aug 2019 18:33:20 +0530 Subject: [PATCH 1/3] updated readme for uisng cli --- README.md | 14 ++++++++++++-- package.json | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ea66df9..57b2eab 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,25 @@ # create-react-webpack -Create React Application with all standard practices, with easy formats known to users, so that users can easily modify the various config files. +Create React Application with all standard practices, with easy formats which is known to users, so that users can easily modify the various config files as needed. ## Creating an App ### npm +### install module + +``` +npm i -g create-react-webpack +``` + +### creating your react app + ``` -npm create-react-webpack demo-app +create-react-webpack demo-app ``` +Once installed globally, above command i.e `create-react-webpack` for bootstraping new application will be available through out the system. + it will create a directory `demo-app` in the current folder, with below file footprint. ``` diff --git a/package.json b/package.json index 93be25b..4d8da6b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "create-react-webpack", - "version": "0.0.1", + "version": "0.0.4", "description": "create-react-webpack ", "main": "scripts/create.js", "bin": { From 08fbdb7de4e2bd0d1c6d5c0ecf8af14725f91ed9 Mon Sep 17 00:00:00 2001 From: alok Date: Mon, 5 Aug 2019 15:35:14 +0530 Subject: [PATCH 2/3] added server for deploying into production --- package.json | 6 +++++- scripts/constants.js | 9 +++++++-- scripts/create.js | 10 ++++++++-- scripts/dependencies.js | 19 +++++++++++++++++- scripts/helper.js | 26 ++++++++++++++++++------ startApp.sh | 3 ++- template/public/favicon.ico | Bin 4286 -> 4286 bytes template/public/index.html | 2 +- template/server/index.js | 24 ++++++++++++++++++++++ template/src/App.css | 22 +++++++++++++++++++++ template/src/App.js | 34 ++++++++++++++++++-------------- template/src/index.js | 2 +- template/webpack.config.prod.js | 5 ++--- 13 files changed, 129 insertions(+), 33 deletions(-) create mode 100644 template/server/index.js diff --git a/package.json b/package.json index 4d8da6b..7ab24ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "create-react-webpack", - "version": "0.0.4", + "version": "0.0.5", "description": "create-react-webpack ", "main": "scripts/create.js", "bin": { @@ -14,6 +14,10 @@ "type": "git", "url": "git+https://github.com/AlokTakshak/create-react-webpack.git" }, + "keywords": [ + "React", + "Webpack" + ], "author": "Alok Takshak", "license": "ISC", "bugs": { diff --git a/scripts/constants.js b/scripts/constants.js index 64a3660..2ad4a2d 100644 --- a/scripts/constants.js +++ b/scripts/constants.js @@ -1,9 +1,14 @@ const CLEAN_NPM_CACHE = "npm cache clean --force"; const SPECIALCHAR = RegExp("/[!@#$%^&*()-=_,.?~:;\\{}|<>]/g"); -const UNNECESSORYFOLDERS = RegExp("^node_modules|build|dist$", "i"); +const UNNECESSORY_FOLDERS_FOR_DEV = RegExp( + "^node_modules|build|dist|server$", + "i" +); +const UNNECESSORY_FOLDERS_FOR_PROD = RegExp("^node_modules|build|dist$", "i"); module.exports = { CLEAN_NPM_CACHE, SPECIALCHAR, - UNNECESSORYFOLDERS + UNNECESSORY_FOLDERS_FOR_DEV, + UNNECESSORY_FOLDERS_FOR_PROD }; diff --git a/scripts/create.js b/scripts/create.js index 636877b..3c39493 100755 --- a/scripts/create.js +++ b/scripts/create.js @@ -4,11 +4,13 @@ const { CLEAN_NPM_CACHE, SPECIALCHAR } = require("./constants"); const { installDependencies, getDependencies, - getDevDependencies + getDevDependencies, + getProdDependencies } = require("./dependencies"); var args = process.argv.slice(2); var dirName = args[0]; +var end_to_end = args[1]; if (dirName[0].match("^[A-Z0-9]")) { throw new Error( @@ -24,14 +26,18 @@ if (dirName[0].match("^[A-Z0-9]")) { //using process.cwd for getting current path const TEMPLATE_PATH = path.join(__dirname, "../template"); let destination = path.join(process.cwd() + "/" + args[0]); - copyDirectory(TEMPLATE_PATH, destination); + const prod = end_to_end == "-e"; + + copyDirectory(TEMPLATE_PATH, destination, prod); let commands = [], options; commands.push(CLEAN_NPM_CACHE); commands.push(getDependencies()); + prod && commands.push(getProdDependencies()); commands.push(getDevDependencies()); + options = { cwd: destination, stdio: "inherit" }; installDependencies(commands, options); diff --git a/scripts/dependencies.js b/scripts/dependencies.js index bf41de8..e6e7c0b 100644 --- a/scripts/dependencies.js +++ b/scripts/dependencies.js @@ -25,6 +25,7 @@ const DEV_DEPENDENCIES = [ "webpack-manifest-plugin", "webpack-merge" ]; +const PROD_DEPENDENCIES = ["express", "express-static-gzip"]; /** * Returns npm command for installing dependencies @@ -48,6 +49,17 @@ function getDevDependencies() { return installCommand; } +/** + * Returns npm command for installing prod dependencies + */ +function getProdDependencies() { + var installCommand = "npm install --save"; + PROD_DEPENDENCIES.forEach(dependency => { + installCommand += ` ${dependency} `; + }); + return installCommand; +} + /** * * @param {Array} commands list of commands needs to be executed @@ -69,4 +81,9 @@ function installDependencies(commands, options) { } } -module.exports = { installDependencies, getDependencies, getDevDependencies }; +module.exports = { + installDependencies, + getDependencies, + getDevDependencies, + getProdDependencies +}; diff --git a/scripts/helper.js b/scripts/helper.js index aed9369..3371d35 100644 --- a/scripts/helper.js +++ b/scripts/helper.js @@ -1,26 +1,35 @@ const fs = require("fs"); const path = require("path"); const chalk = require("chalk"); -const { UNNECESSORYFOLDERS } = require("./constants"); +const { + UNNECESSORY_FOLDERS_FOR_DEV, + UNNECESSORY_FOLDERS_FOR_PROD +} = require("./constants"); /** * @summary copies the directory content from source to destination directory * @param {String} source path of source file * @param {String} destination path of destination file + * @param {boolean} prod tells if user require prod environment */ -function copyDirectory(source, destination) { +function copyDirectory(source, destination, prod) { + let UNNECESSORY_FOLDERS = prod + ? UNNECESSORY_FOLDERS_FOR_PROD + : UNNECESSORY_FOLDERS_FOR_DEV; + createDirectory(destination); var content = fs.readdirSync(source); for (let i = 0; i < content.length; i++) { let currentFile = fs.lstatSync(path.join(source, content[i])); - if (String(content[i]).match(UNNECESSORYFOLDERS)) { + if (String(content[i]).match(UNNECESSORY_FOLDERS)) { continue; } else if (currentFile.isDirectory()) { copyDirectory( path.join(source, content[i]), - path.join(destination, content[i]) + path.join(destination, content[i]), + prod ); } else if (currentFile.isSymbolicLink()) { var symlink = fs.readlinkSync(source, content[i]); @@ -28,7 +37,8 @@ function copyDirectory(source, destination) { } else { copyFile( path.join(source, content[i]), - path.join(destination, content[i]) + path.join(destination, content[i]), + prod ); } } @@ -38,11 +48,15 @@ function copyDirectory(source, destination) { * @summary copies the file content from source to destination file * @param {String} source path of source file * @param {String} destination path of destination file + * @param {boolean} prod tells if user require prod environment */ -function copyFile(source, destination) { +function copyFile(source, destination, prod) { var inputFile, outputFile; if (source.match(".json$")) { inputFile = JSON.parse(fs.readFileSync(source, "utf8")); + if (prod && source.match("package.json$")) { + inputFile.scripts.start = "node server/"; + } fs.writeFileSync(destination, JSON.stringify(inputFile, null, 2), "utf8"); } else { inputFile = fs.createReadStream(source); diff --git a/startApp.sh b/startApp.sh index 2560a27..1828149 100755 --- a/startApp.sh +++ b/startApp.sh @@ -5,6 +5,7 @@ const child_process = require("child_process"); var args = process.argv.slice(2); var dirName = args[0]; +var end_to_end = args[1]; var p=path.join(__dirname,"scripts/create.js") -child_process.execSync(`node ${p} ${dirName}`,{ stdio: "inherit" }); \ No newline at end of file +child_process.execSync(`node ${p} ${dirName} ${end_to_end}`,{ stdio: "inherit" }); \ No newline at end of file diff --git a/template/public/favicon.ico b/template/public/favicon.ico index eb501d247ad2253cbf91102fb97f780c593f93d2..f9272e5d17fd02fc4b50a532e872b1f646f64e14 100644 GIT binary patch literal 4286 zcmb_gc~DjN6~3L$w3)FpN!yt;o&J+J)8&sg$;cR^sJH;4Mi5-UjmIX&jYZivSwv)4 zf{L=Qf<{3>vq+2!E^$STNt8xS&0;h$My)IO^?c`XpO3{(b^4s+ecpF}zwi9M^PS~t z7{8D|FTZT?Z=?PN!+6m!jK7J=En}1z@0*|B4=@Z`@6R88`x^(h!GEcmH*v_7P*2A$ zG4!#?!w}-}CgSIMp{{8Ya?+x(eto`L#7tK#c7L<)n#cQeac^P}%N~E=AAdK&&(+~v zm{&iT-Rp_F)MqRTa#Qfp=bz)`orlQJh(pbmI{AJdEr$*uGbs$=Q%8!AL!ameF^EM> z`XIgxl7F8M_Zr^s8txS)zpaR!kL_)HapLxUoO%Gk>_l#Q3~Ju3#p#F8dq;n|h0Pzd zAT``y_X?TZzaPXRCb7p4{%bY&@1N_TNSHSbwOcphlWRXIM*F=-pq=>lL*YNthOhVU zTm3lr-BnaIR3bijs&Ww`aqGQ5F^L^Kame?*e&d&F z$WDzw?Us!=)7kSk^ZC7BUO-V%9-`((jGHS~wGht5@KYAFf-u>E)xwN&NiaR6Ful#$$>17^@$THEF{R^&F06i)W)@ zXA>C5-njIE_YQsk11jpu5F6kDo+nKFT^<#TEv@h4=#AS?TzCA|U2NOG2O05;5I${G zpLk>~3&;L{T~;l%_j3;Fu4&(Hq%92s<7ppL#w%>9lj^_uP#cclzSqYO@^+>R*mvnG z)v|q#6y&8UkEIpsu#KRGhGo1AN%ieaCIJ=>? z%wMgh#19)Q1CYAN4N3D{^_i$yqxAg5r#36=D)iiD9zPYnoIO5ZEDF=7p{03|Vl{1@ zuh^?orhrBtwl&VzShTb(!kUcf%0Vdgsrcp3jGqYGrdtE`lAl$Q)bj8 zHS%96ai=zmvVD-7Fd5awe#nXQPz_YpJw5)atR%$wjaF4QEb1d48I%bxoD#EXRBEPlSr)t}S@>W>;=EX>%l@!duSkuW%ghbpBjk^^pu%;iuS8L|NPQ6Z!s2}bKgIC0(mm)##mgD9y%V$ z3&v?5u+9OFdiLb`<3tzZ5$)@&vrg;Tv$lRhzFB))Kl@Dkc-qnc<<~YtNDp39kRfx_ z4ef)}pINJU)&4E>3+LaA_z<0WOnz14oJS;1$)OgVgO1<4Ym2pQAMt@bwoQ8A%ES=O zZLT$qGZF7MAKY)7v2AO`2l_-mIGeru;SQul1d1Ocw9iFbCMv%NzP)0_?LM!$p6ibN zd`EnH52;K1b)AVTy|vT!UFr?rF_`Mf0-vnS_&knX~u~#NKXV+WW|P zqqw91QNG>tw;c{K0|ndZ)q#0(e!Dr?8WYu)#5CdU>H3brxmUR`{g89zXC|nflU?g_cqYeo*GHpX8<_X}fahNEc6#-|e|!JpnzV=@jo&eI#_q;vpHl7x zm$|az$YGg-L#^5n|LyQ>--$&`V)GsF#TN#=Hf6-$Tjk6TSi|^^*u%)1?6pMVmm}{y zJC7a~jo#Bam+zyeBo@ruwS}4T-sGw=Cci!Q&^?*wNPpb@+~by(8GusUs^dqa!9PsAI+QxXWdYTP}q7dURNvU+=KE4C-f{ vgWPxcf_oE#SSD_#VK`kfj9>3Dj9(_pe-)T!{GUJOzIz0RcEd29hkX76fV+qF literal 4286 zcmc&&XLnRp6dnJ8Uu=L92_i*tDTs<9s5C)TM6oPgf(7dbT?!abY78PBl$H>x0g)z6 zq@%)%5MzXG&&Lbb%jytef}dy?4*P=bU}c-4BD|7Wo$tVBlZF zfm;oR+YJW8U>S1DFir;V>mknqhr5RBhQR>$(cs8K?uo@nT0I7Fiw7fa(V!kj?6-kP z{Bbl&Vzm#L4nFH`9&OTg?(s!vaO8Sm_3X?y!n|PuqQB{j==ptI zXI}e^sCjoGX5qcC?tTx>f&{d;H7h>X(biOt%c;k3Y4b~n4!RqB*LSY>+HKpsegcTe zqrNH|=5^1>oI7PszwX05CwbHJsJe6*ZOsijucN&U8GGJGNz4}g%|9*mS5X$f1Ew|O zTz=@>?ly^KUiU2OE3=S&=xceGzIJ`DulkV?G7?4S*P^MW(u>0j;#+sm_QUtQ@YmI1 z6rA}1#*h)NSoCCH?qwhP3dZjr>4wkvF^^dXzd&8N)nnHG+|dr}u6Kn8+x+i)e|6|w zVq9D@#3v_iKLy_y{IKTB<9ih26?6|Q+g?R==2^72HhZmgy{NCSY2I><%tveE^{$V- zzdPDmaLpd8YmHqvz`YLl8iXqzY@U-=jX~MPFtjvW^Um*j!5o(g=Mq;wE_3@TCsVh- z28Z>OaHFy7>)zkWQOgnG=!-HZzz>)CPYZif>LSnke%A~7QJr-jmaQ{nu5jFkTg(@0 z&$??iuI0vp@Ah^yUdb05ulU6wbN^?^KKLaH&#eKu)AeY$oP(UhbEU?IB6*e6@rpr+ zVeIBh965p{b|HiGnKAeQ&(Yr6ge$f)NZaui7_XF{rpjE&xAv=6Nf zPLvsU!uHEYC{NfUIdw`NoG6V8)qcZw^CF%?*@=ld3Vs_0n|e!d?z7zpw3~ASc9fD zW8HnPGrzgVze7*>x)677iTwID7f)o3iQnI+{>3inT#qAi8m>gYC z;p!>G$UC*14a4grFa8m~qXXoGwO!dQEQ%w z+G{JN6Z=f#(&8__XYAgZ~qt<|IP~kgln{) z88%7>*W*kOPD(Ez|MGu*TI+;!Z;F4Ct;_?T%UqWxVJ)%#%1=*1%Gw8D*)SZJr4ES4 zI&@r^hSZG@X$>;xT7UE0^-ums-dO!LT((Ppe!+{+9?2N9zk2!)dmM2cQ7^i3F8t`J z|3uEcL-is1zwhDKf0FjQFCnCUI}Bb*Qbv zv#Zs<{b-PA&YaHvD{JH)k+|{+-IKa%0P4J&BD3~mWAHFsT0czo*&!MO=7l3>!QC*+ zJ&QauE*~uKevZ1bbl-66bzMb<>P>3dq*YJpT*inxhB~dKzPj5S&kbs^tJ#rA3x7v7 z4|(mHD;$^nkfX_)rofSQTy&d%u01w*ZmcduYUt~(yec;F`>7_fY@H5A`U$kP{ELoC z{ayCv>EgHOD8Xg?sFBH^-j3G4YEfZ|fO-9RKg}7lpnsWy1Ew%Lan%HO+O%{jr@V9lnzPgRr{FYK3GO874@1FmESY+s8qfS z=$ra0wme+%J?9HH>nt^NreOWU_m|9P-l)^43-u64;%7#DDnDKLsxdQ8!?I<%=GZsZ zzPQ9n-9A&XX^Y>Z*4?wDhfueW%RLNgMTrx&vm^bad~?>R@2oZExTZKo*Fye8Nzd!i zhS(*Bb=RzJ-@x>%(!5`|_n~TI)+l?I@8G@U4HM=2XohIzaP1+5=T^g+7q8!React App -
+
diff --git a/template/server/index.js b/template/server/index.js new file mode 100644 index 0000000..bdccb4b --- /dev/null +++ b/template/server/index.js @@ -0,0 +1,24 @@ +const express = require("express"); +const expressStaticGzip = require("express-static-gzip"); +const path = require("path"); + +const app = express(); +const PORT = process.env.PORT || 3000; + +app.use( + "/", + expressStaticGzip(path.join(process.cwd(), "dist"), { + enableBrotli: true, + orderPreference: ["br", "gz"] + }) +); +app.use(express.static(path.join(process.cwd(), "dist"))); +app.use("/", express.static(path.join(process.cwd(), "public"))); + +app.get("/", (req, res) => { + res.header = res.sendFile(path.join(process.cwd(), "dist", "index.html")); +}); + +app.listen(PORT, () => { + console.log(`Started listening on port: ${PORT}`); +}); diff --git a/template/src/App.css b/template/src/App.css index 4fcade0..4a7393f 100644 --- a/template/src/App.css +++ b/template/src/App.css @@ -9,3 +9,25 @@ html { *:after { box-sizing: inherit; } + +.app { + background-color: antiquewhite; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 98vh; + width: 100%; +} + +.button { + background-color: red; + border-radius: 20px; + color: white; + font-size: 20px; + font-weight: bold; + margin: 10px; + outline: none; + padding-left: 20px; + padding-right: 20px; +} diff --git a/template/src/App.js b/template/src/App.js index 9da646c..a390b49 100644 --- a/template/src/App.js +++ b/template/src/App.js @@ -12,23 +12,27 @@ class App extends Component { render() { return ( -
+

Hello World!

{`Count : ${this.state.count}`}

- - +
+ + +
); } diff --git a/template/src/index.js b/template/src/index.js index 24dd67a..d1d65a2 100644 --- a/template/src/index.js +++ b/template/src/index.js @@ -7,5 +7,5 @@ ReactDOM.render( , - document.getElementById("app") + document.getElementById("root") ); diff --git a/template/webpack.config.prod.js b/template/webpack.config.prod.js index d0be2df..99a58db 100644 --- a/template/webpack.config.prod.js +++ b/template/webpack.config.prod.js @@ -8,10 +8,9 @@ module.exports = merge(baseConfig, { mode: "production", plugins: [ new CompressionPlugin({ - filename: "[path].br[query]", - algorithm: "brotliCompress", + filename: "[path].gz[query]", + algorithm: "gzip", test: /\.(js|css|html|svg)$/, - compressionOptions: { level: 11 }, threshold: 10240, minRatio: 0.8, deleteOriginalAssets: false From 8cc48a143905112dd7bd59e04fd849b15215479f Mon Sep 17 00:00:00 2001 From: alok Date: Mon, 5 Aug 2019 15:44:36 +0530 Subject: [PATCH 3/3] updated readme for prod server --- README.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/README.md b/README.md index 57b2eab..f95e5ee 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,39 @@ demo-app └── webpack.config.prod.js ``` +``` +create-react-webpack demo-app -e +``` + +It incules the node server for deploying into production into your `demo-app`, with below file footprint. + +``` +demo-app +├── README.md +├── node_modules +├── package.json +├── .gitignore +├── .babelrc +├── .eslintrc.json +├── .eslintignore +├── .prettierrc +├── .prettierignore +├── public +│   ├── favicon.ico +│   ├── index.html +│   └── manifest.json +├── server +│   └── index.js +├── src +│   ├── App.css +│   ├── App.js +│   ├── App.spec.js +│   └── index.js +├── webpack.config.base.js +├── webpack.config.dev.js +└── webpack.config.prod.js +``` + ## Available Scripts After creating project directory you can run following scripts:- @@ -56,6 +89,11 @@ After creating project directory you can run following scripts:- builds the application for production to the `dist` folder inside directory.
Uses webpack `prod` `config` along with `base` `config` +### `npm start` + +Start the production server on default port `3000`.
+Read files from `dist` folder. + ### `npm run dev` Start the development server on default port `8080`.