diff --git a/.circleci/config.yml b/.circleci/config.yml index 779bcfe93..20145bee8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -56,8 +56,8 @@ jobs: - attach_workspace: at: ~/coralproject/talk - run: - name: Compile schemas and types - command: npm run compile + name: Generate schemas and types + command: npm run generate - run: name: Perform linting command: npm run lint @@ -74,8 +74,8 @@ jobs: - attach_workspace: at: ~/coralproject/talk - run: - name: Compile schemas and types - command: npm run compile + name: Generate schemas and types + command: npm run generate - run: name: Perform testing # We're running these tests in band to avoid errors where the circleci diff --git a/Dockerfile b/Dockerfile index d7ad7771c..e37c6dada 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ COPY . /usr/src/app # Install build static assets and clear caches. RUN NODE_ENV=development npm install && \ - npm run compile && \ + npm run generate && \ npm run build && \ npm prune --production diff --git a/config/watcher.ts b/config/watcher.ts index e83e7d5b4..8b8e7824a 100644 --- a/config/watcher.ts +++ b/config/watcher.ts @@ -8,13 +8,13 @@ import { const config: Config = { rootDir: path.resolve(__dirname, "../src"), watchers: { - compileSchema: { + generateSchemaTypes: { paths: ["core/server/**/*.graphql"], executor: new CommandExecutor("npx gulp server:schema", { runOnInit: true, }), }, - compileRelayStream: { + generateRelayStream: { paths: [ "core/client/stream/**/*.ts", "core/client/stream/**/*.tsx", @@ -27,11 +27,11 @@ const config: Config = { "**/test/**/*", "core/**/*.spec.*", ], - executor: new CommandExecutor("npm run compile:relay-stream", { + executor: new CommandExecutor("npm run generate:relay-stream", { runOnInit: true, }), }, - compileRelayAdmin: { + generateRelayAdmin: { paths: [ "core/client/admin/**/*.ts", "core/client/admin/**/*.tsx", @@ -44,11 +44,11 @@ const config: Config = { "**/test/**/*", "core/**/*.spec.*", ], - executor: new CommandExecutor("npm run compile:relay-admin", { + executor: new CommandExecutor("npm run generate:relay-admin", { runOnInit: true, }), }, - compileRelayAuth: { + generateRelayAuth: { paths: [ "core/client/auth/**/*.ts", "core/client/auth/**/*.tsx", @@ -61,11 +61,11 @@ const config: Config = { "**/test/**/*", "core/**/*.spec.*", ], - executor: new CommandExecutor("npm run compile:relay-auth", { + executor: new CommandExecutor("npm run generate:relay-auth", { runOnInit: true, }), }, - compileRelayInstall: { + generateRelayInstall: { paths: [ "core/client/install/**/*.ts", "core/client/install/**/*.tsx", @@ -78,13 +78,13 @@ const config: Config = { "**/test/**/*", "core/**/*.spec.*", ], - executor: new CommandExecutor("npm run compile:relay-install", { + executor: new CommandExecutor("npm run generate:relay-install", { runOnInit: true, }), }, - compileCSSTypes: { + generateCSSTypes: { paths: ["**/*.css"], - executor: new CommandExecutor("npm run compile:css-types", { + executor: new CommandExecutor("npm run generate:css-types", { runOnInit: true, }), }, @@ -104,24 +104,24 @@ const config: Config = { }, defaultSet: "client", sets: { - server: ["compileSchema", "runServer"], + server: ["generateSchemaTypes", "runServer"], client: [ "runServer", "runWebpackDevServer", - "compileCSSTypes", - "compileRelayStream", - "compileRelayAuth", - "compileRelayInstall", - "compileRelayAdmin", - "compileSchema", + "generateCSSTypes", + "generateRelayStream", + "generateRelayAuth", + "generateRelayInstall", + "generateRelayAdmin", + "generateSchemaTypes", ], - docz: ["runDocz", "compileCSSTypes"], - compile: [ - "compileSchema", - "compileCSSTypes", - "compileRelayStream", - "compileRelayAuth", - "compileRelayInstall", + docz: ["runDocz", "generate"], + generate: [ + "generateSchemaTypes", + "generateCSSTypes", + "generateRelayStream", + "generateRelayAuth", + "generateRelayInstall", ], }, }; diff --git a/package-lock.json b/package-lock.json index 0a1368d6c..14d4e71c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2087,6 +2087,15 @@ "integrity": "sha512-iiJbKLZbhSa6FYRip/9ZDX6HXhayXLDGY2Fqws9cOkEQ6XeKfaxB0sC541mowZJueYyMnVUmmG+al5/4fCDrgw==", "dev": true }, + "@types/lodash-webpack-plugin": { + "version": "0.11.3", + "resolved": "http://registry.npmjs.org/@types/lodash-webpack-plugin/-/lodash-webpack-plugin-0.11.3.tgz", + "integrity": "sha512-zzwcefaw1wAQZsSWa1ChfhgjtoOTVdzoxSnmuRrGlHnAEF2k+NIAzgJlUc2V2RsvlOaE2WT/CM/zW9m+GX8wAw==", + "dev": true, + "requires": { + "@types/webpack": "*" + } + }, "@types/long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz", @@ -2227,12 +2236,6 @@ "@types/react": "*" } }, - "@types/query-string": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/query-string/-/query-string-6.1.0.tgz", - "integrity": "sha512-6QxF7V3SkdyBRJ81GheWL9Nzr7uDrCZH0hkxdorNcXeBOeAPN5AUf1n9dpecaBOzxJAckWP4nIOeY1YxlhuMTQ==", - "dev": true - }, "@types/range-parser": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.2.tgz", @@ -2421,6 +2424,15 @@ } } }, + "@types/webpack-bundle-analyzer": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@types/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.13.0.tgz", + "integrity": "sha512-+qy5xatScNZW4NbIVaiV38XOeHbKRa4FIPeMf2VDpZEon9W/cxjaVR080vRrRGvfq4tRvOusTEypSMxTvjcSzw==", + "dev": true, + "requires": { + "@types/webpack": "*" + } + }, "@types/webpack-dev-server": { "version": "2.9.5", "resolved": "https://registry.npmjs.org/@types/webpack-dev-server/-/webpack-dev-server-2.9.5.tgz", @@ -3989,6 +4001,35 @@ "integrity": "sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=", "dev": true }, + "babel-plugin-lodash": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/babel-plugin-lodash/-/babel-plugin-lodash-3.3.4.tgz", + "integrity": "sha512-yDZLjK7TCkWl1gpBeBGmuaDIFhZKmkoL+Cu2MUUjv5VxUZx/z7tBGBCBcQs5RI1Bkz5LLmNdjx7paOyQtMovyg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0-beta.49", + "@babel/types": "^7.0.0-beta.49", + "glob": "^7.1.1", + "lodash": "^4.17.10", + "require-package-name": "^2.0.1" + }, + "dependencies": { + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, "babel-plugin-macros": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.0.0.tgz", @@ -5614,6 +5655,18 @@ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" }, + "bfj": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.1.tgz", + "integrity": "sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.1", + "check-types": "^7.3.0", + "hoopy": "^0.1.2", + "tryer": "^1.0.0" + } + }, "big.js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", @@ -6282,6 +6335,12 @@ "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", "dev": true }, + "check-types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-7.4.0.tgz", + "integrity": "sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg==", + "dev": true + }, "cheerio": { "version": "1.0.0-rc.2", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", @@ -9484,8 +9543,7 @@ "dompurify": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-1.0.8.tgz", - "integrity": "sha512-vetRFbN1SXSPfP3ClIiYnxTrXquSqakBEOoB5JESn0SVcSYzpu6ougjakpKnskGctYdlNpwf+riUHSkG7d4XUw==", - "dev": true + "integrity": "sha512-vetRFbN1SXSPfP3ClIiYnxTrXquSqakBEOoB5JESn0SVcSYzpu6ougjakpKnskGctYdlNpwf+riUHSkG7d4XUw==" }, "domutils": { "version": "1.5.1", @@ -10550,6 +10608,12 @@ } } }, + "filesize": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", + "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", + "dev": true + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -12360,6 +12424,16 @@ "glogg": "^1.0.0" } }, + "gzip-size": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.0.0.tgz", + "integrity": "sha512-5iI7omclyqrnWw4XbXAmGhPsABkSIDQonv2K0h61lybgofWa6iZyvrI3r2zsJH4P8Nb64fFVzlvfhs0g7BBxAA==", + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "pify": "^3.0.0" + } + }, "handle-thing": { "version": "1.2.5", "resolved": "http://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", @@ -12607,6 +12681,12 @@ "parse-passwd": "^1.0.0" } }, + "hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", + "dev": true + }, "hosted-git-info": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.1.tgz", @@ -13175,6 +13255,12 @@ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, + "intersection-observer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.5.1.tgz", + "integrity": "sha512-Zd7Plneq82kiXFixs7bX62YnuZ0BMRci9br7io88LwDyF3V43cQMI+G5IiTlTNTt+LsDUppl19J/M2Fp9UkH6g==", + "dev": true + }, "intl-pluralrules": { "version": "github:projectfluent/IntlPluralRules#94cb0fa1c23ad943bc5aafef43cea132fa51d68b", "from": "github:projectfluent/IntlPluralRules#module", @@ -16326,6 +16412,15 @@ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.11.tgz", "integrity": "sha512-DHb1ub+rMjjrxqlB3H56/6MXtm1lSksDp2rA2cNWjG8mlDUYFhUj3Di2Zn5IwSU87xLv8tNIQ7sSwE/YOX/D/Q==" }, + "lodash-webpack-plugin": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/lodash-webpack-plugin/-/lodash-webpack-plugin-0.11.5.tgz", + "integrity": "sha512-QWfEIYxpixOdbd6KBe5g6MDWcyTgP3trDXwKHFqTlXrWiLcs/67fGQ0IWeRyhWlTITQIgMpJAYd2oeIztuV5VA==", + "dev": true, + "requires": { + "lodash": "^4.17.4" + } + }, "lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", @@ -18085,6 +18180,12 @@ "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=", "dev": true }, + "opener": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", + "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==", + "dev": true + }, "opn": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.2.0.tgz", @@ -21129,24 +21230,6 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" }, - "query-string": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.1.0.tgz", - "integrity": "sha512-pNB/Gr8SA8ff8KpUFM36o/WFAlthgaThka5bV19AD9PNTH20Pwq5Zxodif2YyHwrctp6SkL4GqlOot0qR/wGaw==", - "dev": true, - "requires": { - "decode-uri-component": "^0.2.0", - "strict-uri-encode": "^2.0.0" - }, - "dependencies": { - "strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=", - "dev": true - } - } - }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -21160,9 +21243,9 @@ "dev": true }, "querystringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", - "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz", + "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==", "dev": true }, "quick-lru": { @@ -22762,6 +22845,12 @@ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, + "require-package-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz", + "integrity": "sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk=", + "dev": true + }, "require_optional": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", @@ -24638,6 +24727,12 @@ "integrity": "sha512-FHkoUZvG6Egrv9XZAyYGKEyb1JMsFphgPjoczkZC2y6W93U1jswcVURB8MUvtsahEPEVACyxD47JAL63vF4JsQ==", "dev": true }, + "tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", + "dev": true + }, "ts-jest": { "version": "23.0.0", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-23.0.0.tgz", @@ -26013,6 +26108,49 @@ "webpack-sources": "^1.0.1" } }, + "webpack-bundle-analyzer": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.0.3.tgz", + "integrity": "sha512-naLWiRfmtH4UJgtUktRTLw6FdoZJ2RvCR9ePbwM9aRMsS/KjFerkPZG9epEvXRAw5d5oPdrs9+3p+afNjxW8Xw==", + "dev": true, + "requires": { + "acorn": "^5.7.3", + "bfj": "^6.1.1", + "chalk": "^2.4.1", + "commander": "^2.18.0", + "ejs": "^2.6.1", + "express": "^4.16.3", + "filesize": "^3.6.1", + "gzip-size": "^5.0.0", + "lodash": "^4.17.10", + "mkdirp": "^0.5.1", + "opener": "^1.5.1", + "ws": "^6.0.0" + }, + "dependencies": { + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "ws": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.2.tgz", + "integrity": "sha512-rfUqzvz0WxmSXtJpPMX2EeASXabOrSMk1ruMOV3JBTBjo4ac2lDjGGsbQSyxj8Odhw5fBib8ZKEjDNvgouNKYw==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, "webpack-chain": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-4.8.0.tgz", diff --git a/package.json b/package.json index e2c019c92..443d6fc37 100644 --- a/package.json +++ b/package.json @@ -15,16 +15,16 @@ "contributors": "https://github.com/coralproject/talk/graphs/contributors", "description": "A better commenting experience from Mozilla, The Washington Post, and The New York Times.", "scripts": { - "build": "npm-run-all compile --parallel build:*", + "build": "npm-run-all generate --parallel build:*", "build:client": "ts-node ./scripts/build.ts", "build:server": "gulp server", - "compile": "npm-run-all --parallel compile:*", - "compile:css-types": "tcm src/core/client/", - "compile:relay-stream": "ts-node ./scripts/compileRelay --src ./src/core/client/stream --schema tenant", - "compile:relay-auth": "ts-node ./scripts/compileRelay --src ./src/core/client/auth --schema tenant", - "compile:relay-install": "ts-node ./scripts/compileRelay --src ./src/core/client/install --schema tenant", - "compile:relay-admin": "ts-node ./scripts/compileRelay --src ./src/core/client/admin --schema tenant", - "compile:schema": "node ./scripts/generateSchemaTypes.js", + "generate": "npm-run-all --parallel generate:*", + "generate:css-types": "tcm src/core/client/", + "generate:relay-stream": "ts-node ./scripts/compileRelay --src ./src/core/client/stream --schema tenant", + "generate:relay-auth": "ts-node ./scripts/compileRelay --src ./src/core/client/auth --schema tenant", + "generate:relay-install": "ts-node ./scripts/compileRelay --src ./src/core/client/install --schema tenant", + "generate:relay-admin": "ts-node ./scripts/compileRelay --src ./src/core/client/admin --schema tenant", + "generate:schema": "node ./scripts/generateSchemaTypes.js", "docz": "docz", "start": "node dist/index.js", "start:development": "ts-node --project ./src/tsconfig.json -r tsconfig-paths/register ./src/index.ts", @@ -32,14 +32,12 @@ "lint": "npm-run-all --parallel lint:* tscheck:*", "lint:server": "tslint --project ./src/tsconfig.json", "lint:client": "tslint --project ./src/core/client/tsconfig.json", - "lint:client-embed": "tslint --project ./src/core/client/embed/tsconfig.json", "lint:scripts": "tslint --project ./tsconfig.json", "lint-fix": "npm run lint:server -- --fix && npm run lint:client -- --fix && npm run lint:client-embed -- --fix && npm run lint:scripts -- --fix", "test": "node scripts/test.js --env=jsdom", "tscheck": "npm-run-all --parallel tscheck:*", "tscheck:server": "tsc --project ./src/tsconfig.json --noEmit", "tscheck:client": "tsc --project ./src/core/client/tsconfig.json --noEmit", - "tscheck:client-embed": "tsc --project ./src/core/client/embed/tsconfig.json --noEmit", "tscheck:scripts": "tsc --project ./tsconfig.json --noEmit", "watch": "NODE_ENV=development ts-node ./scripts/watcher/bin/watcher.ts --config ./config/watcher.ts" }, @@ -145,6 +143,7 @@ "@types/linkify-it": "^2.0.3", "@types/linkifyjs": "^2.1.0", "@types/lodash": "^4.14.118", + "@types/lodash-webpack-plugin": "^0.11.3", "@types/luxon": "^0.5.3", "@types/mini-css-extract-plugin": "^0.2.0", "@types/mongodb": "^3.1.14", @@ -158,7 +157,6 @@ "@types/passport-local": "^1.0.33", "@types/passport-oauth2": "^1.4.5", "@types/passport-strategy": "^0.2.33", - "@types/query-string": "^6.1.0", "@types/react-copy-to-clipboard": "^4.2.5", "@types/react-dom": "^16.0.6", "@types/react-relay": "^1.3.9", @@ -173,6 +171,7 @@ "@types/uuid": "^3.4.3", "@types/vinyl": "^2.0.2", "@types/webpack": "^4.4.7", + "@types/webpack-bundle-analyzer": "^2.13.0", "@types/webpack-dev-server": "^2.9.5", "@types/webpack-manifest-plugin": "^1.3.2", "@types/ws": "^5.1.2", @@ -180,6 +179,7 @@ "babel-core": "^7.0.0-bridge.0", "babel-jest": "^23.6.0", "babel-loader": "^8.0.0-beta", + "babel-plugin-lodash": "^3.3.4", "babel-plugin-module-resolver": "^3.1.1", "babel-plugin-relay": "^1.7.0-rc.1", "babel-preset-react-optimize": "^1.0.1", @@ -214,6 +214,7 @@ "gulp-typescript": "^5.0.0-alpha.3", "html-webpack-plugin": "^3.2.0", "husky": "^1.1.0", + "intersection-observer": "^0.5.1", "jest": "^23.4.1", "jest-junit": "^5.1.0", "jest-localstorage-mock": "^2.2.0", @@ -221,6 +222,7 @@ "jsdom": "^11.12.0", "lint-staged": "^7.3.0", "loader-utils": "^1.1.0", + "lodash-webpack-plugin": "^0.11.5", "material-design-icons": "^3.0.1", "mini-css-extract-plugin": "^0.4.1", "npm-run-all": "^4.1.3", @@ -237,7 +239,7 @@ "prop-types": "^15.6.2", "pstree.remy": "^1.1.0", "pym.js": "^1.3.2", - "query-string": "^6.1.0", + "querystringify": "^2.1.0", "raw-loader": "^0.5.1", "react": "^16.5.2", "react-copy-to-clipboard": "^5.0.1", @@ -278,6 +280,7 @@ "uglifyjs-webpack-plugin": "^1.2.5", "wait-for-expect": "^1.1.0", "webpack": "4.12.0", + "webpack-bundle-analyzer": "^3.0.3", "webpack-cli": "^3.0.2", "webpack-dev-server": "^3.1.10", "webpack-hot-client": "^4.1.1", diff --git a/scripts/build.ts b/scripts/build.ts index 6cd1f7cc1..58b453ce8 100644 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -15,6 +15,8 @@ import config, { createClientEnv } from "../src/core/common/config"; // Enforce environment to be production. config.validate().set("env", "production"); + +process.env.WEBPACK = "true"; process.env.BABEL_ENV = "production"; process.env.NODE_ENV = "production"; diff --git a/scripts/start.ts b/scripts/start.ts index e35468a14..c5a2a7355 100644 --- a/scripts/start.ts +++ b/scripts/start.ts @@ -17,6 +17,8 @@ import config, { createClientEnv } from "../src/core/common/config"; // Enforce environment to be development. config.validate().set("env", "development"); + +process.env.WEBPACK = "true"; process.env.BABEL_ENV = "development"; process.env.NODE_ENV = "development"; diff --git a/src/core/build/createWebpackConfig.ts b/src/core/build/createWebpackConfig.ts index 847d65772..c0dc38fb6 100644 --- a/src/core/build/createWebpackConfig.ts +++ b/src/core/build/createWebpackConfig.ts @@ -1,17 +1,29 @@ import CaseSensitivePathsPlugin from "case-sensitive-paths-webpack-plugin"; import CompressionPlugin from "compression-webpack-plugin"; import HtmlWebpackPlugin, { Options } from "html-webpack-plugin"; +import { identity } from "lodash"; +import LodashModuleReplacementPlugin from "lodash-webpack-plugin"; import MiniCssExtractPlugin from "mini-css-extract-plugin"; import path from "path"; import InterpolateHtmlPlugin from "react-dev-utils/InterpolateHtmlPlugin"; import WatchMissingNodeModulesPlugin from "react-dev-utils/WatchMissingNodeModulesPlugin"; import TsconfigPathsPlugin from "tsconfig-paths-webpack-plugin"; import UglifyJsPlugin from "uglifyjs-webpack-plugin"; -import webpack, { Configuration } from "webpack"; +import webpack, { Configuration, Plugin } from "webpack"; +import { BundleAnalyzerPlugin } from "webpack-bundle-analyzer"; import ManifestPlugin from "webpack-manifest-plugin"; -import PublicURIWebpackPlugin from "./plugins/PublicURIWebpackPlugin"; import paths from "./paths"; +import PublicURIWebpackPlugin from "./plugins/PublicURIWebpackPlugin"; + +/** + * filterPlugins will filter out null values from the array of plugins, allowing + * easy embedded ternaries. + * + * @param plugins array of plugins and null values + */ +const filterPlugins = (plugins: Array): Plugin[] => + plugins.filter(identity) as Plugin[]; interface CreateWebpackConfig { publicPath?: string; @@ -139,6 +151,9 @@ export default function createWebpackConfig({ new WatchMissingNodeModulesPlugin(paths.appNodeModules), ]; + // If the WEBPACK_STATS environment variable is specified, output the stats! + const includeStats = Boolean(process.env.WEBPACK_STATS); + const baseConfig: Configuration = { // Set webpack mode. mode: isProduction ? "production" : "development", @@ -336,6 +351,9 @@ export default function createWebpackConfig({ { loader: require.resolve("babel-loader"), options: { + // This will ensure that all packages in node_modules that + // import lodash do so in a way that supports tree shaking. + plugins: ["lodash"], presets: [ [ "@babel/env", @@ -399,6 +417,7 @@ export default function createWebpackConfig({ ], }, plugins: [ + new LodashModuleReplacementPlugin(), // Makes some environment variables available to the JS code, for example: // if (process.env.NODE_ENV === 'development') { ... }. See `./env.js`. new webpack.DefinePlugin(envStringified), @@ -473,7 +492,7 @@ export default function createWebpackConfig({ paths.appAdminIndex, ], }, - plugins: [ + plugins: filterPlugins([ ...baseConfig.plugins!, // Generates an `stream.html` file with the