diff --git a/app/package.json b/app/package.json index d8497b6..0efaf23 100644 --- a/app/package.json +++ b/app/package.json @@ -34,6 +34,7 @@ "babel-loader": "^8.2.3", "babel-plugin-formatjs": "^10.3.17", "copy-webpack-plugin": "^10.0.0", + "css-loader": "^6.6.0", "eslint": "^8.8.0", "eslint-config-react-app": "^7.0.0", "eslint-plugin-flowtype": "^8.0.3", @@ -44,6 +45,7 @@ "html-webpack-plugin": "^5.3.1", "jest": "^27.0.4", "jq-cli-wrapper": "^1.6.1", + "mini-css-extract-plugin": "^2.5.3", "msw": "^0.36.3", "node-fetch": "^2.6.1", "shell-loader": "^1.2.1", @@ -58,6 +60,7 @@ "@badrap/bar-of-progress": "^0.1.2", "@emotion/react": "^11.6.0", "@emotion/styled": "^11.6.0", + "@fontsource/roboto": "^4.5.3", "@mui/icons-material": "^5.1.1", "@mui/material": "^5.1.1", "@rehooks/local-storage": "2.4.0", diff --git a/app/src/index.ejs b/app/src/index.ejs index a56898e..5b62b3c 100644 --- a/app/src/index.ejs +++ b/app/src/index.ejs @@ -3,8 +3,6 @@ <%= htmlWebpackPlugin.options.title %> - - diff --git a/app/src/index.tsx b/app/src/index.tsx index 53e799c..4530201 100644 --- a/app/src/index.tsx +++ b/app/src/index.tsx @@ -4,6 +4,11 @@ import * as ReactDOM from "react-dom"; import App from "./app/App"; +import "@fontsource/roboto/300.css"; +import "@fontsource/roboto/400.css"; +import "@fontsource/roboto/500.css"; +import "@fontsource/roboto/700.css"; + declare global { interface Window { /** diff --git a/app/webpack.config.js b/app/webpack.config.js index f59eba6..b6fc7c3 100644 --- a/app/webpack.config.js +++ b/app/webpack.config.js @@ -1,95 +1,106 @@ const CopyPlugin = require("copy-webpack-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin"); +const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const Webpack = require("webpack"); const WorkboxPlugin = require("workbox-webpack-plugin"); -module.exports = { - output: { - clean: true, - publicPath: "/", - chunkFilename: "javascripts/chunks/[chunkhash].[name].js", - filename: "javascripts/[contenthash].[name].js", - }, - module: { - rules: [ - { - test: /\.(png|jpe?g|svg)$/i, - type: "asset/resource", - }, - { - test: /\.tsx?$/, - use: [ - { - loader: "babel-loader", - }, - ], - }, - { - test: /lang\/[a-z_-]+\.json$/i, - type: "json", - use: [ - { - loader: "shell-loader", - options: { - script: - "cat > /tmp/lang.json && formatjs compile /tmp/lang.json --ast", +module.exports = (env, argv) => { + const config = { + output: { + clean: true, + publicPath: "/", + chunkFilename: "javascripts/chunks/[chunkhash].[name].js", + filename: "javascripts/[contenthash].[name].js", + }, + module: { + rules: [ + { + test: /\.(png|jpe?g|svg)$/i, + type: "asset/resource", + }, + { + test: /\.tsx?$/, + use: ["babel-loader"], + }, + { + test: /\.css$/i, + use: [MiniCssExtractPlugin.loader, "css-loader"], + }, + { + test: /lang\/[a-z_-]+\.json$/i, + type: "json", + use: [ + { + loader: "shell-loader", + options: { + script: + "cat > /tmp/lang.json && formatjs compile /tmp/lang.json --ast", + }, }, - }, - ], + ], + }, + ], + }, + resolve: { + alias: { + "@formatjs/icu-messageformat-parser": + "@formatjs/icu-messageformat-parser/no-parser", }, - ], - }, - resolve: { - alias: { - "@formatjs/icu-messageformat-parser": - "@formatjs/icu-messageformat-parser/no-parser", + extensions: [".ts", ".tsx", ".js", ".jsx"], }, - extensions: [".ts", ".tsx", ".js", ".jsx"], - }, - optimization: { - splitChunks: { - chunks: "all", - cacheGroups: { - react: { - test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/, - name: "react", + optimization: { + splitChunks: { + chunks: "all", + cacheGroups: { + react: { + test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/, + name: "react", + }, }, }, }, - }, - plugins: [ - new CopyPlugin({ - patterns: [{ from: "public" }], - }), - new HtmlWebpackPlugin({ - title: "Diversity Puzzle Trails", - meta: { - "theme-color": "#1976d2", - }, - }), - new Webpack.EnvironmentPlugin({ - /** - * API root without trailing slash, e.g. https://example.com/api - */ - API_ROOT: "", + plugins: [ + new CopyPlugin({ + patterns: [{ from: "public" }], + }), + new HtmlWebpackPlugin({ + title: "Diversity Puzzle Trails", + meta: { + "theme-color": "#1976d2", + }, + }), + new Webpack.EnvironmentPlugin({ + /** + * API root without trailing slash, e.g. https://example.com/api + */ + API_ROOT: "", - /** - * Whether to use the mock service worker instead of the real API - */ - API_USE_MOCK: false, - }), - new WorkboxPlugin.GenerateSW({ - exclude: [ - /.+LICENSE\.txt$/, - "mockServiceWorker.js", - "robots.txt", - "_redirects", - "manifest.json", - ], - }), - ], - devServer: { - historyApiFallback: true, - hot: true, - }, + /** + * Whether to use the mock service worker instead of the real API + */ + API_USE_MOCK: false, + }), + new MiniCssExtractPlugin(), + ], + devServer: { + historyApiFallback: true, + hot: true, + }, + }; + + if (argv.mode === "production") { + config.plugins.push( + new WorkboxPlugin.GenerateSW({ + exclude: [ + /.+LICENSE\.txt$/, + "mockServiceWorker.js", + "robots.txt", + "_redirects", + "manifest.json", + ], + }) + ); + } + + return config; }; diff --git a/app/yarn.lock b/app/yarn.lock index 419ecc4..df7abab 100644 --- a/app/yarn.lock +++ b/app/yarn.lock @@ -1188,6 +1188,11 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@fontsource/roboto@^4.5.3": + version "4.5.3" + resolved "https://registry.yarnpkg.com/@fontsource/roboto/-/roboto-4.5.3.tgz#c729ac22c35ae1c224cde10042ce7ab356bc4dda" + integrity sha512-NUvBTj332dFRdiVkLlavXbDGoD2zyyeGYmMyrXOnctg/3e4pq95+rJgNfUP+k4v8UBk2L1aomGw9dDjbRdAmTg== + "@formatjs/cli@^4.2.15": version "4.8.2" resolved "https://registry.yarnpkg.com/@formatjs/cli/-/cli-4.8.2.tgz#65b08c01d0ee0099d56c419ecd49c0bf2f947f56" @@ -3718,6 +3723,20 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== +css-loader@^6.6.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.6.0.tgz#c792ad5510bd1712618b49381bd0310574fafbd3" + integrity sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg== + dependencies: + icss-utils "^5.1.0" + postcss "^8.4.5" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.2.0" + semver "^7.3.5" + css-select@^4.1.3: version "4.2.1" resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd" @@ -3748,6 +3767,11 @@ css@^3.0.0: source-map "^0.6.1" source-map-resolve "^0.6.0" +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + cssom@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" @@ -5508,6 +5532,11 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + idb@^6.1.4: version "6.1.5" resolved "https://registry.yarnpkg.com/idb/-/idb-6.1.5.tgz#dbc53e7adf1ac7c59f9b2bf56e00b4ea4fce8c7b" @@ -7060,6 +7089,13 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== +mini-css-extract-plugin@^2.5.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.3.tgz#c5c79f9b22ce9b4f164e9492267358dbe35376d9" + integrity sha512-YseMB8cs8U/KCaAGQoqYmfUuhhGW0a9p9XvWXrxVOkE3/IiISTLw4ALNt7JR5B2eYauFM+PQGSbXMDmVbR7Tfw== + dependencies: + schema-utils "^4.0.0" + minimalistic-assert@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -7689,7 +7725,48 @@ portfinder@^1.0.28: debug "^3.1.1" mkdirp "^0.5.5" -postcss@^8.1.10: +postcss-modules-extract-imports@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" + integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== + +postcss-modules-local-by-default@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" + integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" + integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== + dependencies: + postcss-selector-parser "^6.0.4" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: + version "6.0.9" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" + integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^8.1.10, postcss@^8.4.5: version "8.4.6" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.6.tgz#c5ff3c3c457a23864f32cb45ac9b741498a09ae1" integrity sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA== @@ -9299,7 +9376,7 @@ url-parse-lax@^1.0.0: dependencies: prepend-http "^1.0.1" -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=