From 96cc05270dbcbd748f6f33990a5029ef0f97f928 Mon Sep 17 00:00:00 2001 From: Joel Chen Date: Thu, 29 Jun 2017 18:23:22 -0700 Subject: [PATCH] [minor] add unbundledJS option --- packages/electrode-react-webapp/README.md | 61 ++++++++++------- .../lib/group-scripts.js | 41 +++++++++++ .../lib/react-webapp.js | 46 +++++++++---- packages/electrode-react-webapp/package.json | 11 +++ .../test/spec/group-scripts.spec.js | 68 +++++++++++++++++++ .../test/spec/index.spec.js | 32 ++++++++- 6 files changed, 221 insertions(+), 38 deletions(-) create mode 100644 packages/electrode-react-webapp/lib/group-scripts.js create mode 100644 packages/electrode-react-webapp/test/spec/group-scripts.spec.js diff --git a/packages/electrode-react-webapp/README.md b/packages/electrode-react-webapp/README.md index 4e1e143ea3..840fa21b5c 100644 --- a/packages/electrode-react-webapp/README.md +++ b/packages/electrode-react-webapp/README.md @@ -7,8 +7,8 @@ a bootstrapping React application. With support for webpack dev server integrat ## Installing -``` -npm install electrode-react-webapp --save +```bash +$ npm install electrode-react-webapp --save ``` ## Usage @@ -45,6 +45,11 @@ const config = { "/{args*}": { view: "index", content: "

Hello React!

" + }, + unbundledJS: { + enterHead: [ + {src: "http://cdn.com/js/lib.js"} + ] } } } @@ -80,23 +85,26 @@ The current defaults are: What you can do with the options: - * `pageTitle` `(String)` The value to be shown in the browser's title bar - * `webpackDev` `(Boolean)` whether to use webpack-dev-server's URLs for retrieving CSS and JS bundles. - * `serverSideRendering` `(Boolean)` Toggle server-side rendering. - * `htmlFile` `(String)` Absolute or relative path to the application root html file. - It must contains the following placeholders: - - `{{PAGE_TITLE}}` page title. - - `{{WEBAPP_BUNDLES}}` injected `\n` + : x.map(n => ``).join("\n") + ) + .join("\n"); + }; + const makeHeaderBundles = helmet => { const manifest = bundleManifest(); - const manifestLink = manifest ? `` : ""; + const manifestLink = manifest ? `\n` : ""; const css = bundleCss(); - const cssLink = css && !criticalCSS - ? `` - : ""; + const cssLink = css && !criticalCSS ? `` : ""; const scriptsFromHelmet = ["link", "style", "script", "noscript"] - .map((tagName) => helmet[tagName].toString()).join(""); + .map(tagName => helmet[tagName].toString()) + .join(""); - return `${manifestLink}${cssLink}${scriptsFromHelmet}`; + const htmlScripts = htmlifyScripts(groupScripts(routeOptions.unbundledJS.enterHead).scripts); + return `${manifestLink}${cssLink}${htmlScripts}\n${scriptsFromHelmet}`; }; const makeBodyBundles = () => { const js = bundleJs(); - const css = bundleCss(); - const cssLink = css && criticalCSS ? `` : ""; - const jsLink = js ? `` : ""; + const jsLink = js ? { src: js } : ""; - return `${cssLink}${jsLink}`; + const ins = routeOptions.unbundledJS.preBundle + .concat([jsLink]) + .concat(routeOptions.unbundledJS.postBundle); + const htmlScripts = htmlifyScripts(groupScripts(ins).scripts); + + return `${htmlScripts}`; }; const emptyTitleRegex = /]*><\/title>/; @@ -221,7 +236,7 @@ function makeRouteHandler(routeOptions, userContent) { case HEADER_BUNDLE_MARKER: return makeHeaderBundles(helmet); case BODY_BUNDLE_MARKER: - return makeBodyBundles(helmet); + return makeBodyBundles(); case PREFETCH_MARKER: return ``; case META_TAGS_MARKER: @@ -257,6 +272,11 @@ const setupOptions = options => { port: process.env.WEBPACK_DEV_PORT || "2992", https: Boolean(process.env.WEBPACK_DEV_HTTPS) }, + unbundledJS: { + enterHead: [], + preBundle: [], + postBundle: [] + }, paths: {}, stats: "dist/server/stats.json", iconStats: "dist/server/iconstats.json", @@ -269,7 +289,7 @@ const setupOptions = options => { const chunkSelector = resolveChunkSelector(pluginOptions); const devProtocol = process.env.WEBPACK_DEV_HTTPS ? "https://" : "http://"; const devBundleBase = `${devProtocol}${pluginOptions.devServer.host}:${pluginOptions.devServer - .port}/js/`; // eslint-disable-line max-len + .port}/js/`; const statsPath = getStatsPath(pluginOptions.stats, pluginOptions.buildArtifacts); return Promise.try(() => loadAssetsFromStats(statsPath)).then(assets => { @@ -287,7 +307,7 @@ const resolveContent = content => { if (!_.isString(content) && !_.isFunction(content) && content.module) { const module = content.module.startsWith(".") ? Path.join(process.cwd(), content.module) - : content.module; // eslint-disable-line + : content.module; return require(module); // eslint-disable-line } diff --git a/packages/electrode-react-webapp/package.json b/packages/electrode-react-webapp/package.json index 6cdbe351d1..e42f4ef635 100644 --- a/packages/electrode-react-webapp/package.json +++ b/packages/electrode-react-webapp/package.json @@ -54,5 +54,16 @@ "superagent": "^1.6.1", "uglify-js": "^2.6.2", "xclap": "^0.2.0" + }, + "nyc": { + "all": true, + "check-coverage": true, + "statements": 94.02, + "branches": 76.11, + "functions": 97.96, + "lines": 93.82, + "cache": true, + "reporter": ["lcov", "text", "text-summary"], + "exclude": ["coverage", "*clap.js", "gulpfile.js", "dist", "test", "lib/express", "lib/koa"] } } diff --git a/packages/electrode-react-webapp/test/spec/group-scripts.spec.js b/packages/electrode-react-webapp/test/spec/group-scripts.spec.js new file mode 100644 index 0000000000..9ce7cb3c77 --- /dev/null +++ b/packages/electrode-react-webapp/test/spec/group-scripts.spec.js @@ -0,0 +1,68 @@ +"use strict"; + +const data = [ + "a", + "b", + "c", + { src: 1 }, + { src: 5, defer: 1 }, + { src: 2 }, + "d", + "e", + "f", + "g", + { src: 3 }, + "h", + "i", + "j", + { + src: 4, + async: 1 + }, + { src: 10 }, + "k", + "l", + "m" +]; + +const groupScripts = require("../../lib/group-scripts"); +const chai = require("chai"); + +describe("group-scripts", function() { + it("should group scripts", () => { + const expected = [ + "a;\n\nb;\n\nc;", + [ + { + src: 1 + }, + { + src: 5, + defer: 1 + }, + { + src: 2 + } + ], + "d;\n\ne;\n\nf;\n\ng;", + [ + { + src: 3 + } + ], + "h;\n\ni;\n\nj;", + [ + { + src: 4, + async: 1 + }, + { + src: 10 + } + ], + "k;\n\nl;\n\nm;" + ]; + const result = groupScripts(data); + chai.expect(result.scripts).to.deep.equal(expected); + }); +}); diff --git a/packages/electrode-react-webapp/test/spec/index.spec.js b/packages/electrode-react-webapp/test/spec/index.spec.js index 0a187034a2..a42633df0d 100644 --- a/packages/electrode-react-webapp/test/spec/index.spec.js +++ b/packages/electrode-react-webapp/test/spec/index.spec.js @@ -184,10 +184,10 @@ describe("Test electrode-react-webapp", () => { .then(res => { expect(res.statusCode).to.equal(200); expect(res.result).to.contain( - '