webpack.config.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. const path = require("path");
  2. const HtmlWebpackPlugin = require("html-webpack-plugin");
  3. const webpack = require("webpack");
  4. const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
  5. const dotenv = require("dotenv");
  6. const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  7. .BundleAnalyzerPlugin;
  8. const TerserPlugin = require("terser-webpack-plugin");
  9. module.exports = () => {
  10. const env = dotenv.config().parsed;
  11. const envKeys = Object.keys(env).reduce((prev, next) => {
  12. prev[`process.env.${next}`] = JSON.stringify(env[next]);
  13. return prev;
  14. }, {});
  15. // Check first the env file and if it's empty, check out the node env of the process.
  16. let isDevelopment = env.NODE_ENV !== "production";
  17. if (process.env.NODE_ENV !== env.NODE_ENV) {
  18. isDevelopment = process.env.NODE_ENV !== "production";
  19. }
  20. /**
  21. * @type {webpack.Configuration}
  22. */
  23. const config = {
  24. entry: ["./src/index.tsx"],
  25. target: "web",
  26. mode: isDevelopment ? "development" : "production",
  27. devtool: "source-map",
  28. module: {
  29. rules: [
  30. {
  31. test: /\.(ts|tsx|mjs|js|jsx)$/,
  32. exclude: /node_modules/,
  33. use: [
  34. {
  35. loader: require.resolve("babel-loader"),
  36. options: {
  37. plugins: [
  38. isDevelopment && require.resolve("react-refresh/babel"),
  39. ].filter(Boolean),
  40. },
  41. },
  42. ],
  43. },
  44. {
  45. enforce: "pre",
  46. test: /\.js$/,
  47. loader: "source-map-loader",
  48. },
  49. {
  50. test: /\.(png|svg|jpg|gif|mp3)$/,
  51. use: ["file-loader"],
  52. },
  53. { test: /\.css$/, use: ["css-loader"] },
  54. {
  55. test: /\.(woff(2)?|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
  56. use: [
  57. {
  58. loader: "file-loader",
  59. options: {
  60. name: "[name].[ext]",
  61. outputPath: "fonts/",
  62. },
  63. },
  64. ],
  65. },
  66. ],
  67. },
  68. resolve: {
  69. modules: [path.resolve(__dirname, "src"), "node_modules"],
  70. extensions: ["*", ".tsx", ".ts", ".js", ".jsx", ".json"],
  71. },
  72. output: {
  73. filename: "bundle.js",
  74. path: path.resolve(__dirname, "build"),
  75. publicPath: "/",
  76. },
  77. devServer: {
  78. historyApiFallback: true,
  79. disableHostCheck: true,
  80. host: "0.0.0.0",
  81. port: env.DEV_SERVER_PORT || 8080,
  82. hot: true,
  83. },
  84. plugins: [
  85. new HtmlWebpackPlugin({
  86. template: path.resolve(__dirname, "src", "index.html"),
  87. segmentKey: `${process.env.SEGMENT_PUBLIC_KEY}`,
  88. }),
  89. new webpack.DefinePlugin(envKeys),
  90. isDevelopment && new ReactRefreshWebpackPlugin(),
  91. ].filter(Boolean),
  92. };
  93. if (!isDevelopment) {
  94. config.optimization = {
  95. minimize: true,
  96. minimizer: [
  97. new TerserPlugin({
  98. test: /\.(ts|tsx|mjs|js|jsx)$/,
  99. terserOptions: {
  100. parse: {
  101. // We want terser to parse ecma 8 code. However, we don't want it
  102. // to apply minification steps that turns valid ecma 5 code
  103. // into invalid ecma 5 code. This is why the `compress` and `output`
  104. ecma: 8,
  105. },
  106. compress: {
  107. ecma: 5,
  108. warnings: false,
  109. inline: 2,
  110. },
  111. mangle: {
  112. // Find work around for Safari 10+
  113. safari10: true,
  114. },
  115. output: {
  116. ecma: 5,
  117. comments: false,
  118. ascii_only: true,
  119. },
  120. },
  121. // Use multi-process parallel running to improve the build speed
  122. parallel: true,
  123. }),
  124. ],
  125. };
  126. }
  127. if (env.ENABLE_ANALYZER) {
  128. config.plugins.push(new BundleAnalyzerPlugin());
  129. }
  130. if (env.ENABLE_PROXY) {
  131. if (!env.API_SERVER) {
  132. throw new Error(
  133. "API_SERVER is not present on .env! Please setup the api server url if you want the proxy to work! API_SERVER example: http://localhost:8080"
  134. );
  135. }
  136. config.devServer.proxy = {
  137. "/api": {
  138. logLevel: "debug",
  139. target: env.API_SERVER, // target host
  140. changeOrigin: true, // needed for virtual hosted sites
  141. ws: true, // proxy websockets
  142. },
  143. };
  144. }
  145. return config;
  146. };