webpack.config.js 4.7 KB

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