diff --git a/.gitignore b/.gitignore index 7eb7aa98b..eae3dc85c 100644 --- a/.gitignore +++ b/.gitignore @@ -517,3 +517,5 @@ yarn.lock npm-debug.log* yarn-debug.log* yarn-error.log* +.fyn + diff --git a/packages/xarc-app-dev/package.json b/packages/xarc-app-dev/package.json index 17bb7b515..ee06c19f0 100644 --- a/packages/xarc-app-dev/package.json +++ b/packages/xarc-app-dev/package.json @@ -49,6 +49,7 @@ "@babel/plugin-transform-runtime": "^7.1.0", "@babel/preset-env": "^7.1.6", "@babel/preset-react": "^7.0.0", + "@babel/preset-typescript": "^7.0.0", "@babel/register": "^7.0.0", "@jchip/redbird": "^1.1.2", "@loadable/babel-plugin": "^5.10.0", diff --git a/packages/xarc-app-dev/src/config/babel/common.ts b/packages/xarc-app-dev/src/config/babel/common.ts index 14ad944b4..eb003bf4a 100644 --- a/packages/xarc-app-dev/src/config/babel/common.ts +++ b/packages/xarc-app-dev/src/config/babel/common.ts @@ -1,9 +1,6 @@ /* eslint-disable @typescript-eslint/no-var-requires */ -const ck = require("chalker"); import * as requireAt from "require-at"; -const Path = require("path"); -const Fs = require("fs"); // // Resolve full path of a plugin that's the dependency of host npm package @@ -22,29 +19,4 @@ export function getPluginFrom(host, pluginName) { throw err; } -export function loadXarcOptions(dir: string) { - dir = dir || process.cwd(); - const filename = Path.join(dir, ".etmp/xarc-options.json"); - try { - const data = Fs.readFileSync(filename, "utf-8"); - return JSON.parse(data); - } catch (err) { - // eslint-disable-next-line - console.error(ck` -ERROR: Electrode xarc fail to load .etmp/xarc-options.json in -dev mode. This means you are trying to use something not through -xarc's development tasks. - -full path: ${filename} - -Please run "clap setup-dev" once to initialize the file -.etmp/xarc-options.json before doing your thing that loads -xarc's development code. -`); - return { - webpack: {}, - babel: {}, - options: {} - }; - } -} +export { loadXarcOptions } from "../../lib/utils"; diff --git a/packages/xarc-app-dev/src/config/jest/jest.config.ts b/packages/xarc-app-dev/src/config/jest/jest.config.ts index dd9881213..2c0180525 100644 --- a/packages/xarc-app-dev/src/config/jest/jest.config.ts +++ b/packages/xarc-app-dev/src/config/jest/jest.config.ts @@ -1,5 +1,4 @@ /* eslint-disable @typescript-eslint/no-var-requires */ -export {}; const Path = require("path"); const _ = require("lodash"); @@ -11,9 +10,11 @@ const optRequire = getOptArchetypeRequire(["@xarc/opt-jest", "electrode-archetyp const jestPkg = optRequire("jest/package.json"); const jestMajVersion = parseInt(jestPkg.version.split(".")[0], 10); -const archetype = require("@xarc/app/config/archetype")(); +import { loadXarcOptions } from "../../lib/utils"; -const { enableTypeScript } = archetype.babel; +const xarcOptions = loadXarcOptions(); + +const { enableTypeScript } = xarcOptions.babel; // https://jestjs.io/docs/en/configuration.html#testregex-string const scrTypes = enableTypeScript ? "jt" : "j"; @@ -55,5 +56,5 @@ module.exports = _.merge( {}, _.pickBy(jestDefaultConfig, x => x !== undefined), jestVersionSpecificConfig[jestMajVersion], - archetype.jest + xarcOptions.jest ); diff --git a/packages/xarc-app-dev/src/config/karma/browser-settings.ts b/packages/xarc-app-dev/src/config/karma/browser-settings.ts index 32b087bcd..e66b09ce1 100644 --- a/packages/xarc-app-dev/src/config/karma/browser-settings.ts +++ b/packages/xarc-app-dev/src/config/karma/browser-settings.ts @@ -1,10 +1,11 @@ /* eslint-disable @typescript-eslint/no-var-requires, no-process-exit */ -export {}; + +import { loadXarcOptions } from "../../lib/utils"; module.exports = function(settings) { - const archetype = require("@xarc/app/config/archetype")(); + const xarcOptions = loadXarcOptions(); const logger = require("@xarc/app/lib/logger"); - const browser = archetype.karma.browser.toLowerCase(); + const browser = xarcOptions.karma.browser.toLowerCase(); if (browser === "chrome") { settings.browsers = ["ChromeHeadless"]; diff --git a/packages/xarc-app-dev/src/lib/babel-run.ts b/packages/xarc-app-dev/src/lib/babel-run.ts index 2aedb8225..a93fb5042 100644 --- a/packages/xarc-app-dev/src/lib/babel-run.ts +++ b/packages/xarc-app-dev/src/lib/babel-run.ts @@ -15,6 +15,8 @@ export {}; */ const Path = require("path"); +import { loadXarcOptions } from "../lib/utils"; + const serverDir = process.argv[2] || "src/server"; let start; @@ -23,7 +25,7 @@ try { // Try to load user's dev.js under src/server start = require(Path.resolve(serverDir, "dev.js")); } catch (e) { - const archetype = require("../config/archetype")(); + const xarcOptions = loadXarcOptions(); const cwdNM = Path.resolve("node_modules"); const cwd = process.cwd(); @@ -37,7 +39,7 @@ try { } ], extensions: [".js", ".jsx"] - .concat(archetype.babel.enableTypeScript && [".ts", ".tsx"]) + .concat(xarcOptions.babel.enableTypeScript && [".ts", ".tsx"]) .filter(x => x), cache: true }); diff --git a/packages/xarc-app-dev/src/lib/dev-admin/dev-server.ts b/packages/xarc-app-dev/src/lib/dev-admin/dev-server.ts index a2cf915d4..4e3c5fca4 100644 --- a/packages/xarc-app-dev/src/lib/dev-admin/dev-server.ts +++ b/packages/xarc-app-dev/src/lib/dev-admin/dev-server.ts @@ -4,7 +4,6 @@ import { setupHttpDevServer } from "./dev-http"; import { createServer } from "http"; const ck = require("chalker"); -const archetype = require("../../config/archetype")(); const optionalRequire = require("optional-require")(require); const fastifyServer = optionalRequire("@xarc/fastify-server"); const electrodeServer = optionalRequire("electrode-server"); @@ -12,6 +11,10 @@ const Hapi = optionalRequire("@hapi/hapi"); const Koa = optionalRequire("koa"); const express = optionalRequire("express"); +import { loadXarcOptions } from "../../lib/utils"; + +const xarcOptions = loadXarcOptions(); + // // indicate that app is running in webpack dev mode // also set by @xarc/app/arch-clap.js @@ -22,8 +25,8 @@ if (process.env.WEBPACK_DEV === undefined) { if (createServer) { const devHttpServer = setupHttpDevServer({ - host: archetype.webpack.devHostname, - port: archetype.webpack.devPort + host: xarcOptions.webpack.devHostname, + port: xarcOptions.webpack.devPort }); devHttpServer.addListener("error", err => { console.error(ck`HTTP webpack dev server having an error${err}`); @@ -31,7 +34,7 @@ if (createServer) { devHttpServer.addListener("listening", () => console.log( - ck`Node.js webpack dev server listening on port ${archetype.webpack.devPort}` + ck`Node.js webpack dev server listening on port ${xarcOptions.webpack.devPort}` ) ); devHttpServer.start(); @@ -42,8 +45,8 @@ if (createServer) { pinoOptions: false }, connection: { - host: archetype.webpack.devHostname, - port: archetype.webpack.devPort + host: xarcOptions.webpack.devHostname, + port: xarcOptions.webpack.devPort }, plugins: { webpackDevFastify: { @@ -58,7 +61,7 @@ if (createServer) { logLevel: "warn" }, connections: { - default: { host: archetype.webpack.devHostname, port: archetype.webpack.devPort } + default: { host: xarcOptions.webpack.devHostname, port: xarcOptions.webpack.devPort } }, plugins: { webpackDevHapi: { @@ -69,15 +72,15 @@ if (createServer) { }); } else if (Hapi) { const app = Hapi.server({ - port: archetype.webpack.devPort, - host: archetype.webpack.devHostname + port: xarcOptions.webpack.devPort, + host: xarcOptions.webpack.devHostname }); app .register(require("./dev-hapi")) .then(() => app.start()) .then(() => { console.log( - ck`Hapi webpack dev server listening on port ${archetype.webpack.devPort}` + ck`Hapi webpack dev server listening on port ${xarcOptions.webpack.devPort}` ); }) .catch(err => { @@ -87,12 +90,12 @@ if (createServer) { const app = new Koa(); const setup = require("./dev-koa"); setup(app); - app.listen(archetype.webpack.devPort, err => { + app.listen(xarcOptions.webpack.devPort, err => { if (err) { console.error(ck`koa webpack dev server failed${err}`); } else { console.log( - ck`koa webpack dev server listening on port ${archetype.webpack.devPort}` + ck`koa webpack dev server listening on port ${xarcOptions.webpack.devPort}` ); } }); @@ -100,12 +103,12 @@ if (createServer) { const app = express(); const setup = require("./dev-express"); setup(app); - app.listen(archetype.webpack.devPort, err => { + app.listen(xarcOptions.webpack.devPort, err => { if (err) { console.error(ck`express webpack dev server failed${err}`); } else { console.log( - ck`express webpack dev server listening on port ${archetype.webpack.devPort}` + ck`express webpack dev server listening on port ${xarcOptions.webpack.devPort}` ); } }); diff --git a/packages/xarc-app-dev/src/lib/utils.ts b/packages/xarc-app-dev/src/lib/utils.ts index b0a396b41..bf4c74ab4 100644 --- a/packages/xarc-app-dev/src/lib/utils.ts +++ b/packages/xarc-app-dev/src/lib/utils.ts @@ -4,7 +4,7 @@ import * as readPkgUp from "read-pkg-up"; import * as pkgUp from "pkg-up"; const mkdirp = require("mkdirp"); const logger = require("./logger"); - +const ck = require("chalker"); const Path = require("path"); const Fs = require("fs"); @@ -67,3 +67,34 @@ export function createGitIgnoreDir(dir, comment) { Fs.writeFileSync(gitIgnore, `# ${comment}\n*\n`); } } + +let cachedXarcOptions; + +export function loadXarcOptions(dir: string = process.cwd()) { + if (cachedXarcOptions) { + return cachedXarcOptions; + } + const filename = Path.join(dir, ".etmp/xarc-options.json"); + try { + const data = Fs.readFileSync(filename, "utf-8"); + return (cachedXarcOptions = JSON.parse(data)); + } catch (err) { + // eslint-disable-next-line + console.error(ck` +ERROR: Electrode xarc fail to load .etmp/xarc-options.json in +dev mode. This means you are trying to use something not through +xarc's development tasks. + +full path: ${filename} + +Please run "clap setup-dev" once to initialize the file +.etmp/xarc-options.json before doing your thing that loads +xarc's development code. +`); + return (cachedXarcOptions = { + webpack: {}, + babel: {}, + options: {} + }); + } +} diff --git a/packages/xarc-webpack/src/partials/babel.ts b/packages/xarc-webpack/src/partials/babel.ts index 1c5295519..8e6350a25 100644 --- a/packages/xarc-webpack/src/partials/babel.ts +++ b/packages/xarc-webpack/src/partials/babel.ts @@ -1,13 +1,16 @@ /* eslint-disable @typescript-eslint/no-var-requires */ import * as Path from "path"; -const archetype = require("@xarc/app-dev/config/archetype")(); -const AppMode = archetype.AppMode; const identity = require("lodash/identity"); const assign = require("lodash/assign"); const babelLoader = require.resolve("babel-loader"); +import { loadXarcOptions } from "../util/load-xarc-options"; + module.exports = function(options) { + const xarcOptions = loadXarcOptions(); + const AppMode = xarcOptions.AppMode; + const clientVendor = Path.join(AppMode.src.client, "vendor/"); const babelExclude = x => { if (x.indexOf("node_modules") >= 0) return true; @@ -15,7 +18,7 @@ module.exports = function(options) { return false; }; - const test = archetype.babel.enableTypeScript ? /\.[tj]sx?$/ : /\.jsx?$/; + const test = xarcOptions.babel.enableTypeScript ? /\.[tj]sx?$/ : /\.jsx?$/; const babelLoaderConfig = { _name: "babel", @@ -38,7 +41,7 @@ module.exports = function(options) { assign( {}, babelLoaderConfig, - archetype.babel.hasMultiTargets ? archetype.babel.extendLoader : {} + xarcOptions.babel.hasMultiTargets ? xarcOptions.babel.extendLoader : {} ) ] } diff --git a/packages/xarc-webpack/src/partials/dev.ts b/packages/xarc-webpack/src/partials/dev.ts index 032618963..8689d4b75 100644 --- a/packages/xarc-webpack/src/partials/dev.ts +++ b/packages/xarc-webpack/src/partials/dev.ts @@ -2,27 +2,29 @@ import * as Url from "url"; // const MiniCssExtractPlugin = require("mini-css-extract-plugin"); -const archetype = require("@xarc/app-dev/config/archetype")(); const webpackDevReporter = require("../util/webpack-dev-reporter"); +import { loadXarcOptions } from "../util/load-xarc-options"; const HTTP_PORT = 80; -const devProtocol = archetype.webpack.https ? "https://" : "http://"; - module.exports = function() { + const xarcOptions = loadXarcOptions(); + + const devProtocol = xarcOptions.webpack.https ? "https://" : "http://"; + const devServerConfig: any = { - hot: archetype.webpack.enableHotModuleReload, + hot: xarcOptions.webpack.enableHotModuleReload, overlay: { errors: true, - warnings: archetype.webpack.enableWarningsOverlay + warnings: xarcOptions.webpack.enableWarningsOverlay }, reporter: webpackDevReporter, - https: Boolean(archetype.webpack.https) + https: Boolean(xarcOptions.webpack.https) }; if (process.env.WEBPACK_DEV_HOST || process.env.WEBPACK_HOST) { - devServerConfig.public = `${archetype.webpack.devHostname}:${archetype.webpack.devPort}`; - const orginUrl = `${devProtocol}${archetype.webpack.devHostname}:${archetype.webpack.devPort}`; + devServerConfig.public = `${xarcOptions.webpack.devHostname}:${xarcOptions.webpack.devPort}`; + const orginUrl = `${devProtocol}${xarcOptions.webpack.devHostname}:${xarcOptions.webpack.devPort}`; devServerConfig.headers = { "Access-Control-Allow-Origin": orginUrl }; @@ -41,7 +43,7 @@ module.exports = function() { // const makePublicPath = () => { // is any of the webpack.cdn* options defined - const { cdnProtocol, cdnHostname, cdnPort } = archetype.webpack; + const { cdnProtocol, cdnHostname, cdnPort } = xarcOptions.webpack; if (cdnProtocol !== null || cdnHostname !== null || cdnPort !== 0) { return Url.format({ protocol: cdnProtocol || "http", @@ -54,7 +56,7 @@ module.exports = function() { // under the same host and port, so use a relative path return "/js/"; } else { - const { https, devHostname, devPort } = archetype.webpack; + const { https, devHostname, devPort } = xarcOptions.webpack; // original dev assets URLs return Url.format({ protocol: https ? "https" : "http", diff --git a/packages/xarc-webpack/src/partials/dll-entry.ts b/packages/xarc-webpack/src/partials/dll-entry.ts index 3ae6a93de..36bb1560f 100644 --- a/packages/xarc-webpack/src/partials/dll-entry.ts +++ b/packages/xarc-webpack/src/partials/dll-entry.ts @@ -1,11 +1,12 @@ /* eslint-disable @typescript-eslint/no-var-requires */ import * as Path from "path"; - -const archetypeConfig = require("@xarc/app-dev/config/archetype"); +import { loadXarcOptions } from "../util/load-xarc-options"; module.exports = () => { - const AppMode = archetypeConfig().AppMode; + const xarcOptions = loadXarcOptions(); + const AppMode = xarcOptions.AppMode; + const clientDllConfig = require(Path.resolve(AppMode.src.client, "dll.config.js")); return { diff --git a/packages/xarc-webpack/src/partials/dll-reference.ts b/packages/xarc-webpack/src/partials/dll-reference.ts index 45e734430..909f1c0ad 100644 --- a/packages/xarc-webpack/src/partials/dll-reference.ts +++ b/packages/xarc-webpack/src/partials/dll-reference.ts @@ -11,15 +11,17 @@ import * as fs from "fs"; import * as Path from "path"; import * as webpack from "webpack"; const filterScanDir = require("filter-scan-dir"); -const archetype = require("@xarc/app-dev/config/archetype")(); +import { loadXarcOptions } from "../util/load-xarc-options"; const logger = require("@xarc/app-dev/lib/logger"); module.exports = function(options) { + const xarcOptions = loadXarcOptions(); + const config = options.currentConfig; logger.verbose("add-dll-references configurations", JSON.stringify(config, null, 2)); try { - const exists = fs.existsSync(Path.resolve(archetype.AppMode.src.client, "dll.config.js")); + const exists = fs.existsSync(Path.resolve(xarcOptions.AppMode.src.client, "dll.config.js")); const filenames = filterScanDir.sync({ dir: Path.resolve("dll", "js"), includeRoot: true, diff --git a/packages/xarc-webpack/src/partials/entry.ts b/packages/xarc-webpack/src/partials/entry.ts index 1bd26799e..ca604224c 100644 --- a/packages/xarc-webpack/src/partials/entry.ts +++ b/packages/xarc-webpack/src/partials/entry.ts @@ -6,15 +6,17 @@ import * as Fs from "fs"; import * as Path from "path"; import * as _ from "lodash"; const optionalRequire = require("optional-require")(require); -const archetype = require("@xarc/app-dev/config/archetype")(); -const AppMode = archetype.AppMode; const chalk = require("chalk"); const logger = require("@xarc/app-dev/lib/logger"); const mkdirp = require("mkdirp"); +import { loadXarcOptions } from "../util/load-xarc-options"; const DEV_HMR_DIR = ".__dev_hmr"; function makeEntryPartial() { + const xarcOptions = loadXarcOptions(); + const AppMode = xarcOptions.AppMode; + const partial: any = { context: Path.resolve(AppMode.src.client) }; @@ -152,7 +154,7 @@ if (module.hot) { const entryConfig = searchEntryConfig(); if (entryConfig) return entryConfig; - if (archetype.options.subapp !== false) { + if (xarcOptions.options.subapp !== false) { // App has subapp apps within src? const subApps = searchSubApps(); if (subApps) { @@ -173,13 +175,13 @@ if (module.hot) { } function shouldPolyfill() { - if (archetype.webpack.enableBabelPolyfill) { + if (xarcOptions.webpack.enableBabelPolyfill) { const hasMultipleTarget = - Object.keys(archetype.babel.envTargets) + Object.keys(xarcOptions.babel.envTargets) .sort() .join(",") !== "default,node"; if (hasMultipleTarget) { - return archetype.babel.target === "default"; + return xarcOptions.babel.target === "default"; // for all other targets, disable polyfill } else { return true; diff --git a/packages/xarc-webpack/src/partials/extract-style.ts b/packages/xarc-webpack/src/partials/extract-style.ts index 077d150b2..2f1122c29 100644 --- a/packages/xarc-webpack/src/partials/extract-style.ts +++ b/packages/xarc-webpack/src/partials/extract-style.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-var-requires, max-statements */ import * as Path from "path"; -const archetypeConfig = require("@xarc/app-dev/config/archetype"); +import { loadXarcOptions } from "../util/load-xarc-options"; const detectCssModule = require("../util/detect-css-module"); @@ -67,9 +67,10 @@ function loadPostCss() { */ module.exports = function() { + const xarcOptions = loadXarcOptions(); + const isProduction = process.env.NODE_ENV === "production"; const isDevelopment = !isProduction; - const archetype = archetypeConfig(); const cssModuleSupport = detectCssModule(); @@ -101,7 +102,7 @@ module.exports = function() { * css-modules Loader */ const getCSSModuleOptions = () => { - const enableShortenCSSNames = archetype.webpack.enableShortenCSSNames; + const enableShortenCSSNames = xarcOptions.webpack.enableShortenCSSNames; const enableShortHash = isProduction && enableShortenCSSNames; const localIdentName = `${enableShortHash ? "" : "[name]__[local]___"}[hash:base64:5]`; @@ -153,7 +154,7 @@ module.exports = function() { * SASS */ - if (archetype.options.sass && sassLoader) { + if (xarcOptions.options.sass && sassLoader) { rules.push({ _name: `${namePrefix}-scss`, test: /\.(scss|sass)$/, @@ -211,7 +212,7 @@ module.exports = function() { } const styleBundleFilename = - process.env.WEBPACK_DEV || archetype.babel.hasMultiTargets + process.env.WEBPACK_DEV || xarcOptions.babel.hasMultiTargets ? "[name].style.css" : "[name].style.[contenthash].css"; @@ -219,7 +220,7 @@ module.exports = function() { module: { rules }, plugins: [ new MiniCssExtractPlugin({ filename: styleBundleFilename }), - isProduction && new OptimizeCssAssetsPlugin(archetype.webpack.optimizeCssOptions), + isProduction && new OptimizeCssAssetsPlugin(xarcOptions.webpack.optimizeCssOptions), new webpack.LoaderOptionsPlugin({ minimize: true, options: { context: Path.resolve("src") } diff --git a/packages/xarc-webpack/src/partials/fonts.ts b/packages/xarc-webpack/src/partials/fonts.ts index a67d41d3f..0d0bdb333 100644 --- a/packages/xarc-webpack/src/partials/fonts.ts +++ b/packages/xarc-webpack/src/partials/fonts.ts @@ -1,9 +1,9 @@ /* eslint-disable @typescript-eslint/no-var-requires */ -const archetypeConfig = require("@xarc/app-dev/config/archetype"); +import { loadXarcOptions } from "../util/load-xarc-options"; module.exports = function() { - const archetype = archetypeConfig(); + const xarcOptions = loadXarcOptions(); const urlLoader = require.resolve("url-loader"); const fileLoader = require.resolve("file-loader"); const isomorphicLoader = require.resolve("isomorphic-loader"); @@ -18,7 +18,7 @@ module.exports = function() { { loader: urlLoader, options: { - limit: archetype.webpack.woffFontInlineLimit, + limit: xarcOptions.webpack.woffFontInlineLimit, mimetype: "application/font-woff" } }, diff --git a/packages/xarc-webpack/src/partials/isomorphic.ts b/packages/xarc-webpack/src/partials/isomorphic.ts index 88b419d27..2ad95d0bd 100644 --- a/packages/xarc-webpack/src/partials/isomorphic.ts +++ b/packages/xarc-webpack/src/partials/isomorphic.ts @@ -1,15 +1,15 @@ /* eslint-disable @typescript-eslint/no-var-requires */ import { IsomorphicLoaderPlugin } from "isomorphic-loader"; -const archetypeConfig = require("@xarc/app-dev/config/archetype"); +import { loadXarcOptions } from "../util/load-xarc-options"; module.exports = function(opts) { - const archetype = archetypeConfig(); + const xarcOptions = loadXarcOptions(); const plugin = new IsomorphicLoaderPlugin({ assetsFile: opts.assetsFile || "../isomorphic-assets.json", webpackDev: { - url: `http://${archetype.webpack.devHostname}:${archetype.webpack.devPort}`, + url: `http://${xarcOptions.webpack.devHostname}:${xarcOptions.webpack.devPort}`, addUrl: false } }); diff --git a/packages/xarc-webpack/src/partials/loadable.ts b/packages/xarc-webpack/src/partials/loadable.ts index e2280ebd5..91fbeb0f4 100644 --- a/packages/xarc-webpack/src/partials/loadable.ts +++ b/packages/xarc-webpack/src/partials/loadable.ts @@ -1,12 +1,12 @@ /* eslint-disable @typescript-eslint/no-var-requires */ -const archetypeConfig = require("@xarc/app-dev/config/archetype"); +import { loadXarcOptions } from "../util/load-xarc-options"; import * as LoadablePlugin from "@loadable/webpack-plugin"; module.exports = function() { - const archetype = archetypeConfig(); + const xarcOptions = loadXarcOptions(); return { - plugins: archetype.babel.enableDynamicImport + plugins: xarcOptions.babel.enableDynamicImport ? [new LoadablePlugin({ filename: "../server/loadable-stats.json" })] : [] }; diff --git a/packages/xarc-webpack/src/partials/node.ts b/packages/xarc-webpack/src/partials/node.ts index a9d153c5d..9eade2079 100644 --- a/packages/xarc-webpack/src/partials/node.ts +++ b/packages/xarc-webpack/src/partials/node.ts @@ -1,19 +1,16 @@ /* eslint-disable @typescript-eslint/no-var-requires */ -const archetypeConfig = require("@xarc/app-dev/config/archetype"); +import { loadXarcOptions } from "../util/load-xarc-options"; const logger = require("@xarc/app-dev/lib/logger"); -// https://stackoverflow.com/questions/40900791/cannot-redeclare-block-scoped-variable-in-unrelated-files -export {}; - module.exports = function(options) { - const archetype = archetypeConfig(); + const xarcOptions = loadXarcOptions(); const config = options.currentConfig; if ( process.env.NODE_ENV === "production" && config.target === undefined && - archetype.webpack.enableNodeSourcePlugin !== true + xarcOptions.webpack.enableNodeSourcePlugin !== true ) { logger.info("Disabling NodeSourcePlugin for production"); return { node: false }; diff --git a/packages/xarc-webpack/src/partials/output.ts b/packages/xarc-webpack/src/partials/output.ts index faa92a2bf..ed92e091b 100644 --- a/packages/xarc-webpack/src/partials/output.ts +++ b/packages/xarc-webpack/src/partials/output.ts @@ -1,10 +1,10 @@ /* eslint-disable @typescript-eslint/no-var-requires */ import * as Path from "path"; -const archetypeConfig = require("@xarc/app-dev/config/archetype"); +import { loadXarcOptions } from "../util/load-xarc-options"; module.exports = () => { - const { AppMode, babel } = archetypeConfig(); + const { babel } = loadXarcOptions(); const inspectpack = process.env.INSPECTPACK_DEBUG === "true"; diff --git a/packages/xarc-webpack/src/partials/prod-mode.ts b/packages/xarc-webpack/src/partials/prod-mode.ts index 5e52145e0..6f1b822e9 100644 --- a/packages/xarc-webpack/src/partials/prod-mode.ts +++ b/packages/xarc-webpack/src/partials/prod-mode.ts @@ -1,12 +1,11 @@ /* eslint-disable @typescript-eslint/no-var-requires */ -const archetype = require("@xarc/app-dev/config/archetype")(); - -// https://stackoverflow.com/questions/40900791/cannot-redeclare-block-scoped-variable-in-unrelated-files -export {}; +import { loadXarcOptions } from "../util/load-xarc-options"; module.exports = function() { + const xarcOptions = loadXarcOptions(); + return { - mode: archetype.webpack.minify ? "production" : "development" + mode: xarcOptions.webpack.minify ? "production" : "development" }; }; diff --git a/packages/xarc-webpack/src/partials/pwa.ts b/packages/xarc-webpack/src/partials/pwa.ts index 8db6081c7..e7cc3bfff 100644 --- a/packages/xarc-webpack/src/partials/pwa.ts +++ b/packages/xarc-webpack/src/partials/pwa.ts @@ -1,9 +1,8 @@ /* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/camelcase */ import * as Path from "path"; -const archetype = require("@xarc/app-dev/config/archetype")(); const requireAt = require("require-at"); -const AppMode = archetype.AppMode; +import { loadXarcOptions } from "../util/load-xarc-options"; const assign = require("lodash/assign"); const fileLoader = require.resolve("file-loader"); @@ -63,8 +62,11 @@ function createEntryConfigFromScripts(importScripts, entry) { } module.exports = function(options) { + const xarcOptions = loadXarcOptions(); + const AppMode = xarcOptions.AppMode; + /* eslint max-statements: 0 */ - const swConfig = (archetype.options.pwa && optionalRequire(swConfigPath, true)) || {}; + const swConfig = (xarcOptions.options.pwa && optionalRequire(swConfigPath, true)) || {}; if (!swConfig.manifest) { return {}; diff --git a/packages/xarc-webpack/src/partials/resolve-loader.ts b/packages/xarc-webpack/src/partials/resolve-loader.ts index 9387a5244..bce463f4b 100644 --- a/packages/xarc-webpack/src/partials/resolve-loader.ts +++ b/packages/xarc-webpack/src/partials/resolve-loader.ts @@ -4,14 +4,18 @@ import * as Path from "path"; const identity = require("lodash/identity"); const ModuleResolver = require("electrode-node-resolver/lib/webpack-plugin"); -const archetype = require("@xarc/app-dev/config/archetype")(); +import { loadXarcOptions } from "../util/load-xarc-options"; -module.exports = () => ({ - resolveLoader: { - symlinks: !archetype.webpack.preserveSymlinks, - modules: [Path.resolve("lib"), process.cwd()] - .concat(archetype.webpack.loaderDirectories) - .filter(identity), - plugins: [new ModuleResolver("module", "resolve", archetype.devDir, undefined)] - } -}); +module.exports = () => { + const xarcOptions = loadXarcOptions(); + + return { + resolveLoader: { + symlinks: !xarcOptions.webpack.preserveSymlinks, + modules: [Path.resolve("lib"), process.cwd()] + .concat(xarcOptions.webpack.loaderDirectories) + .filter(identity), + plugins: [new ModuleResolver("module", "resolve", xarcOptions.devDir, undefined)] + } + }; +}; diff --git a/packages/xarc-webpack/src/partials/resolve.ts b/packages/xarc-webpack/src/partials/resolve.ts index c09c6a22f..23e2d10b3 100644 --- a/packages/xarc-webpack/src/partials/resolve.ts +++ b/packages/xarc-webpack/src/partials/resolve.ts @@ -2,56 +2,60 @@ import * as Path from "path"; -const archetype = require("@xarc/app-dev/config/archetype")(); -const AppMode = archetype.AppMode; const ModuleResolver = require("electrode-node-resolver/lib/webpack-plugin"); const identity = require("lodash/identity"); +import { loadXarcOptions } from "../util/load-xarc-options"; -function infernoReactAlias() { - switch (AppMode.reactLib) { - case "inferno": - return { - react: "inferno-compat", - "react-dom": "inferno-compat", - "react-dom/server": "inferno-compat" - }; - case "preact": - return { - react: "preact/compat", - "react-dom": "preact/compat", - "react-dom/server": "preact/compat" - }; - default: - return {}; +module.exports = () => { + const xarcOptions = loadXarcOptions(); + const AppMode = xarcOptions.AppMode; + + function infernoReactAlias() { + switch (AppMode.reactLib) { + case "inferno": + return { + react: "inferno-compat", + "react-dom": "inferno-compat", + "react-dom/server": "inferno-compat" + }; + case "preact": + return { + react: "preact/compat", + "react-dom": "preact/compat", + "react-dom/server": "preact/compat" + }; + default: + return {}; + } } -} - -const { enableTypeScript } = archetype.babel; - -const resolve: any = { - alias: infernoReactAlias(), - // https://webpack.js.org/configuration/resolve/#resolve-symlinks - symlinks: !archetype.webpack.preserveSymlinks, - // Add a resolver plugin that looks up in the archetype first. - // Note that webpack will use this first before trying its default - // plugins and the modules paths specified below - plugins: [new ModuleResolver("module", "resolve", archetype.devDir, undefined)], - modules: [Path.resolve(AppMode.src.dir), process.cwd(), "node_modules"] - .concat(archetype.webpack.modulesDirectories) - .filter(identity), - extensions: [".js", ".jsx", ".json"].concat(enableTypeScript && [".ts", ".tsx"]).filter(x => x) -}; -// -// Prioritize `module` over `browser` field in package.json -// -// This really should be the default for all to make treeshaking work -// but since it will likely be a breaking change, it's only done for subapps for now -// it will be done in next major version as default for all -// https://github.com/electrode-io/electrode/issues/1491 -// -if (AppMode.hasSubApps) { - resolve.mainFields = ["module", "browser", "main"]; -} - -module.exports = () => ({ resolve }); + const { enableTypeScript } = xarcOptions.babel; + + const resolve: any = { + alias: infernoReactAlias(), + // https://webpack.js.org/configuration/resolve/#resolve-symlinks + symlinks: !xarcOptions.webpack.preserveSymlinks, + // Add a resolver plugin that looks up in the archetype first. + // Note that webpack will use this first before trying its default + // plugins and the modules paths specified below + plugins: [new ModuleResolver("module", "resolve", xarcOptions.devDir, undefined)], + modules: [Path.resolve(AppMode.src.dir), process.cwd(), "node_modules"] + .concat(xarcOptions.webpack.modulesDirectories) + .filter(identity), + extensions: [".js", ".jsx", ".json"].concat(enableTypeScript && [".ts", ".tsx"]).filter(x => x) + }; + + // + // Prioritize `module` over `browser` field in package.json + // + // This really should be the default for all to make treeshaking work + // but since it will likely be a breaking change, it's only done for subapps for now + // it will be done in next major version as default for all + // https://github.com/electrode-io/electrode/issues/1491 + // + if (AppMode.hasSubApps) { + resolve.mainFields = ["module", "browser", "main"]; + } + + return { resolve }; +}; diff --git a/packages/xarc-webpack/src/partials/stats.ts b/packages/xarc-webpack/src/partials/stats.ts index 27b66ad48..dd28260b8 100644 --- a/packages/xarc-webpack/src/partials/stats.ts +++ b/packages/xarc-webpack/src/partials/stats.ts @@ -8,9 +8,11 @@ import * as _ from "lodash"; const mkdirp = require("mkdirp"); const INDENT = 2; -const archetype = require("@xarc/app-dev/config/archetype")(); +import { loadXarcOptions } from "../util/load-xarc-options"; module.exports = function(opts) { + const xarcOptions = loadXarcOptions(); + const StatsWriterPlugin = require("webpack-stats-plugin").StatsWriterPlugin; const statsOptions: any = { @@ -48,7 +50,7 @@ module.exports = function(opts) { // statsOptions.transform = data => { cleanupChunks(data); - const dir = archetype.webpack.devArtifactsPath || archetype.eTmpDir; + const dir = xarcOptions.webpack.devArtifactsPath || xarcOptions.eTmpDir; mkdirp.sync(dir); const str = JSON.stringify(data, null, INDENT); Fs.writeFileSync(Path.resolve(dir, "stats.json"), str); diff --git a/packages/xarc-webpack/src/partials/subapp-chunks.ts b/packages/xarc-webpack/src/partials/subapp-chunks.ts index b459de6e7..8df35f6ce 100644 --- a/packages/xarc-webpack/src/partials/subapp-chunks.ts +++ b/packages/xarc-webpack/src/partials/subapp-chunks.ts @@ -3,6 +3,7 @@ /* eslint-disable global-require, no-magic-numbers */ import * as Crypto from "crypto"; +import { loadXarcOptions } from "../util/load-xarc-options"; const splitMap = {}; @@ -22,7 +23,7 @@ function hashChunks(mod, chunks, key) { } function makeConfig() { - const { AppMode, webpack } = require("@xarc/app-dev/config/archetype")(); + const { AppMode, webpack } = loadXarcOptions(); const config: any = {}; diff --git a/packages/xarc-webpack/src/util/custom-check.ts b/packages/xarc-webpack/src/util/custom-check.ts index 68529fa97..4ed2ff902 100644 --- a/packages/xarc-webpack/src/util/custom-check.ts +++ b/packages/xarc-webpack/src/util/custom-check.ts @@ -5,13 +5,15 @@ import * as Fs from "fs"; import * as Path from "path"; -const archetype = require("@xarc/app-dev/config/archetype")(); +import { loadXarcOptions } from "../util/load-xarc-options"; function useAppWebpackConfig() { return process.env.USE_APP_WEBPACK_CONFIG === "true"; } function getWebpackStartConfig(defaultFile: string, relativeToCwd = true) { + const archetype = loadXarcOptions(); + const customFilePath = Path.resolve("webpack.config.js"); const canUseAppProfile = useAppWebpackConfig() && Fs.existsSync(customFilePath); diff --git a/packages/xarc-webpack/src/util/detect-css-module.ts b/packages/xarc-webpack/src/util/detect-css-module.ts index 7d8ec7afe..a92da82f2 100644 --- a/packages/xarc-webpack/src/util/detect-css-module.ts +++ b/packages/xarc-webpack/src/util/detect-css-module.ts @@ -3,11 +3,13 @@ import * as Path from "path"; const filterScanDir = require("filter-scan-dir"); -const archetype = require("@xarc/app-dev/config/archetype")(); -const AppMode = archetype.AppMode; const getOptRequire = require("../util/get-opt-require"); +import { loadXarcOptions } from "../util/load-xarc-options"; function detectCSSModule() { + const archetype = loadXarcOptions(); + const AppMode = archetype.AppMode; + // if user explicitly says they want CSS module support, then we enable it if (archetype.webpack.cssModuleSupport !== undefined) { return Boolean(archetype.webpack.cssModuleSupport); diff --git a/packages/xarc-webpack/src/util/dll-util.ts b/packages/xarc-webpack/src/util/dll-util.ts index 076cefc86..99e589191 100644 --- a/packages/xarc-webpack/src/util/dll-util.ts +++ b/packages/xarc-webpack/src/util/dll-util.ts @@ -22,7 +22,7 @@ import * as _ from "lodash"; import * as Path from "path"; const logger = require("@xarc/app-dev/lib/logger"); -const archetype = require("@xarc/app-dev/config/archetype")(); +import { loadXarcOptions } from "../util/load-xarc-options"; const mkdirp = require("mkdirp"); const { devServerBaseUrl } = require("../util/webpack-dev-url"); const requireAt = require("require-at"); @@ -119,6 +119,8 @@ const verifyVersions = info => { const electrodeDllDevBasePath = "__electrode_dev/dll"; const updateDllAssetsForDev = dllAssets => { + const archetype = loadXarcOptions(); + const baseUrl = devServerBaseUrl(archetype.webpack); const tag = getEnvTag(); @@ -138,6 +140,8 @@ module.exports = { loadJson, updateDllAssetsForDev, loadAssets: () => { + const archetype = loadXarcOptions(); + const loadDlls = archetype.webpack.loadDlls; const dllMods = Object.keys(loadDlls).filter(x => loadDlls[x] && loadDlls[x].enable !== false); diff --git a/packages/xarc-webpack/src/util/load-xarc-options.ts b/packages/xarc-webpack/src/util/load-xarc-options.ts new file mode 100644 index 000000000..ee0249de0 --- /dev/null +++ b/packages/xarc-webpack/src/util/load-xarc-options.ts @@ -0,0 +1,37 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ + +const ck = require("chalker"); +const Path = require("path"); +const Fs = require("fs"); + +let loaded; + +export function loadXarcOptions(dir: string = process.cwd()) { + if (loaded) { + return loaded; + } + dir = dir || process.cwd(); + const filename = Path.join(dir, ".etmp/xarc-options.json"); + try { + const data = Fs.readFileSync(filename, "utf-8"); + return (loaded = JSON.parse(data)); + } catch (err) { + // eslint-disable-next-line + console.error(ck` +ERROR: Electrode xarc fail to load .etmp/xarc-options.json in +dev mode. This means you are trying to use something not through +xarc's development tasks. + +full path: ${filename} + +Please run "clap setup-dev" once to initialize the file +.etmp/xarc-options.json before doing your thing that loads +xarc's development code. +`); + return (loaded = { + webpack: {}, + babel: {}, + options: {} + }); + } +} diff --git a/packages/xarc-webpack/src/util/notify-bundle-valid.ts b/packages/xarc-webpack/src/util/notify-bundle-valid.ts index be3172890..16e6b0fce 100644 --- a/packages/xarc-webpack/src/util/notify-bundle-valid.ts +++ b/packages/xarc-webpack/src/util/notify-bundle-valid.ts @@ -4,9 +4,11 @@ import * as Fs from "fs"; import * as Path from "path"; -const archetype = require("@xarc/app-dev/config/archetype")(); +import { loadXarcOptions } from "../util/load-xarc-options"; module.exports = function notifyBundleValid() { + const archetype = loadXarcOptions(); + setTimeout(() => { Fs.writeFileSync(Path.resolve(archetype.eTmpDir, "bundle.valid.log"), `${Date.now()}`); }, 100);