| "use strict"; | |
| const autoprefixer = require("autoprefixer"); | |
| const SWPrecacheWebpackPlugin = require("sw-precache-webpack-plugin"); | |
| const DefinePlugin = require("webpack/lib/DefinePlugin"); | |
| const UglifyJsPlugin = require("webpack/lib/optimize/UglifyJsPlugin"); | |
| const HtmlWebpackPlugin = require("html-webpack-plugin"); | |
| const ExtractTextPlugin = require("extract-text-webpack-plugin"); | |
| const AssetsPlugin = require("assets-webpack-plugin"); | |
| const InterpolateHtmlPlugin = require("react-dev-utils/InterpolateHtmlPlugin"); | |
| const getClientEnvironment = require("./env"); | |
| const tailwindcss = require("tailwindcss"); | |
| const paths = require("../config/paths"); | |
| // Webpack uses `publicPath` to determine where the app is being served from. | |
| // It requires a trailing slash, or the file assets will get an incorrect path. | |
| const publicPath = process.env.PUBLIC_URL; | |
| // Some apps do not use client-side routing with pushState. | |
| // For these, "homepage" can be set to "." to enable relative asset paths. | |
| const shouldUseRelativeAssetPaths = publicPath === "./"; | |
| // `publicUrl` is just like `publicPath`, but we will provide it to our app | |
| // as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript. | |
| // Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz. | |
| const publicUrl = publicPath.slice(0, -1); | |
| // Get environment variables to inject into our app. | |
| const env = getClientEnvironment(publicUrl); | |
| // Note: defined here because it will be used more than once. | |
| const cssFilename = "static/css/[name].[contenthash:8].css"; | |
| // ExtractTextPlugin expects the build output to be flat. | |
| // (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27) | |
| // However, our output is structured with css, js and media folders. | |
| // To have this structure working with relative paths, we have to use custom options. | |
| const extractTextPluginOptions = shouldUseRelativeAssetPaths | |
| ? // Making sure that the publicPath goes back to to build folder. | |
| { publicPath: Array(cssFilename.split("/").length).join("../") } | |
| : {}; | |
| const PurgecssPlugin = require("purgecss-webpack-plugin"); | |
| //https://tailwindcss.com/docs/controlling-file-size | |
| // https://github.com/FullHuman/purgecss#extractor | |
| class TailwindExtractor { | |
| static extract(content) { | |
| return content.match(/[A-z0-9-:\/]+/g) || []; | |
| } | |
| } | |
| module.exports = { | |
| bail: true, | |
| entry: [paths.appIndexJs], | |
| output: { | |
| // The build folder. | |
| path: paths.appBuild, | |
| // Append leading slash when production assets are referenced in the html. | |
| publicPath: publicPath, | |
| // Add /* filename */ comments to generated require()s in the output. | |
| pathinfo: true, | |
| // Generated JS files. | |
| filename: "static/js/[name].[chunkhash:8].js", | |
| }, | |
| resolve: { | |
| modules: ["node_modules"], | |
| extensions: [".js", ".elm"], | |
| }, | |
| module: { | |
| noParse: /\.elm$/, | |
| rules: [ | |
| { | |
| test: /\.jsx?$/, | |
| exclude: [/elm-stuff/, /node_modules/], | |
| loader: require.resolve("babel-loader"), | |
| }, | |
| { | |
| test: /\.elm$/, | |
| exclude: [/elm-stuff/, /node_modules/], | |
| use: [ | |
| { | |
| loader: require.resolve("string-replace-loader"), | |
| query: { | |
| multiple: [ | |
| { | |
| search: "%PUBLIC_URL%", | |
| replace: publicUrl, | |
| }, | |
| { | |
| search: "%API_URL%", | |
| replace: process.env.API_URL, | |
| }, | |
| ], | |
| }, | |
| }, | |
| { | |
| // Use the local installation of elm-make | |
| loader: require.resolve("elm-webpack-loader"), | |
| options: { | |
| debug: process.env.ELM_DEBUGGER === "true" ? true : false, | |
| pathToMake: paths.elmMake, | |
| }, | |
| }, | |
| ], | |
| }, | |
| { | |
| test: /\.css$/, | |
| use: [ | |
| require.resolve("style-loader"), | |
| { | |
| loader: require.resolve("css-loader"), | |
| options: { | |
| importLoaders: 1, | |
| }, | |
| }, | |
| { | |
| loader: require.resolve("postcss-loader"), | |
| options: { | |
| ident: "postcss", // https://webpack.js.org/guides/migrating/#complex-options | |
| plugins: () => [ | |
| autoprefixer({ | |
| browsers: [ | |
| ">1%", | |
| "last 4 versions", | |
| "Firefox ESR", | |
| "not ie < 9", | |
| ], | |
| }), | |
| ], | |
| }, | |
| }, | |
| ], | |
| }, | |
| { | |
| test: /\.scss$/, | |
| use: ExtractTextPlugin.extract( | |
| Object.assign( | |
| { | |
| fallback: "style-loader", | |
| use: [ | |
| { | |
| loader: "css-loader", | |
| options: { | |
| includePaths: [paths.node_modules], | |
| sourceMap: true, | |
| }, | |
| }, | |
| { | |
| loader: "postcss-loader", | |
| options: { | |
| ident: "postcss", // https://webpack.js.org/guides/migrating/#complex-options | |
| sourceMap: true, | |
| plugins: () => [ | |
| autoprefixer({ | |
| browsers: [ | |
| ">1%", | |
| "last 4 versions", | |
| "Firefox ESR", | |
| "not ie < 9", | |
| ], | |
| }), | |
| tailwindcss("./config/tailwind.js"), | |
| ], | |
| }, | |
| }, | |
| { | |
| loader: "sass-loader", | |
| options: { | |
| includePaths: [paths.node_modules], | |
| sourceMap: true, | |
| }, | |
| }, | |
| ], | |
| }, | |
| extractTextPluginOptions | |
| ) | |
| ), | |
| }, | |
| { | |
| exclude: [ | |
| /\.html$/, | |
| /\.js$/, | |
| /\.elm$/, | |
| /\.css$/, | |
| /\.scss$/, | |
| /\.json$/, | |
| /\.svg$/, | |
| ], | |
| loader: require.resolve("url-loader"), | |
| options: { | |
| limit: 10000, | |
| name: "static/media/[name].[hash:8].[ext]", | |
| }, | |
| }, | |
| // "file" loader for svg | |
| { | |
| test: /\.svg$/, | |
| loader: require.resolve("file-loader"), | |
| options: { | |
| name: "static/media/[name].[hash:8].[ext]", | |
| }, | |
| }, | |
| ], | |
| }, | |
| plugins: [ | |
| new AssetsPlugin({ path: paths.appBuild }), | |
| new DefinePlugin(env.stringified), | |
| new InterpolateHtmlPlugin(env.raw), | |
| /* Minify the compiled JavaScript. */ | |
| /* new UglifyJsPlugin({ | |
| * compress: { | |
| * warnings: false, | |
| * dead_code: true, | |
| * pure_funcs: [ | |
| * "_elm_lang$core$Native_Utils.update", | |
| * "A2", | |
| * "A3", | |
| * "A4", | |
| * "A5", | |
| * "A6", | |
| * "A7", | |
| * "A8", | |
| * "A9", | |
| * "F2", | |
| * "F3", | |
| * "F4", | |
| * "F5", | |
| * "F6", | |
| * "F7", | |
| * "F8", | |
| * "F9", | |
| * ], | |
| * }, | |
| * output: { | |
| * comments: false, | |
| * }, | |
| * }), */ | |
| new HtmlWebpackPlugin({ | |
| inject: true, | |
| template: paths.appHtml, | |
| minify: { | |
| removeComments: true, | |
| collapseWhitespace: true, | |
| removeRedundantAttributes: true, | |
| useShortDoctype: true, | |
| removeEmptyAttributes: true, | |
| removeStyleLinkTypeAttributes: true, | |
| keepClosingSlash: true, | |
| minifyJS: true, | |
| minifyCSS: true, | |
| minifyURLs: true, | |
| }, | |
| }), | |
| // Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`. | |
| new ExtractTextPlugin({ | |
| filename: cssFilename, | |
| }), | |
| // Generate a service worker script that will precache, and keep up to date, | |
| // the HTML & assets that are part of the Webpack build. | |
| new SWPrecacheWebpackPlugin({ | |
| // By default, a cache-busting query parameter is appended to requests | |
| // used to populate the caches, to ensure the responses are fresh. | |
| // If a URL is already hashed by Webpack, then there is no concern | |
| // about it being stale, and the cache-busting can be skipped. | |
| dontCacheBustUrlsMatching: /\.\w{8}\./, | |
| filename: "service-worker.js", | |
| logger(message) { | |
| if (message.indexOf("Total precache size is") === 0) { | |
| // This message occurs for every build and is a bit too noisy. | |
| return; | |
| } | |
| if (message.indexOf("Skipping static resource") === 0) { | |
| // This message obscures real errors so we ignore it. | |
| // https://github.com/facebookincubator/create-react-app/issues/2612 | |
| return; | |
| } | |
| console.log(message); | |
| }, | |
| minify: true, | |
| // For unknown URLs, fallback to the index page | |
| navigateFallback: publicUrl + "/index.html", | |
| // Ignores URLs starting from /__ (useful for Firebase): | |
| // https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219 | |
| navigateFallbackWhitelist: [/^(?!\/__).*/], | |
| // Don't precache sourcemaps (they're large) and build asset manifest: | |
| staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/], | |
| }), | |
| ], | |
| // Some libraries import Node modules but don't use them in the browser. | |
| // Tell Webpack to provide empty mocks for them so importing them works. | |
| node: { | |
| dgram: "empty", | |
| fs: "empty", | |
| net: "empty", | |
| tls: "empty", | |
| child_process: "empty", | |
| }, | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment