]> Untitled Git - lemmy-ui.git/blob - webpack.config.js
fix submodule error
[lemmy-ui.git] / webpack.config.js
1 const webpack = require("webpack");
2 const { resolve } = require("path");
3 const MiniCssExtractPlugin = require("mini-css-extract-plugin");
4 const nodeExternals = require("webpack-node-externals");
5 const CopyPlugin = require("copy-webpack-plugin");
6 const { ServiceWorkerPlugin } = require("service-worker-webpack");
7
8 const banner = `
9   hash:[contentHash], chunkhash:[chunkhash], name:[name], filebase:[base], query:[query], file:[file]
10   Source code: https://github.com/LemmyNet/lemmy-ui
11   Created by dessalines
12   @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL v3.0
13   `;
14
15 module.exports = (env, argv) => {
16   const mode = argv.mode;
17
18   const base = {
19     output: {
20       hashFunction: "xxhash64",
21     },
22     resolve: {
23       extensions: [".js", ".jsx", ".ts", ".tsx"],
24       alias: {
25         "@": resolve(__dirname, "src/"),
26         "@utils": resolve(__dirname, "src/shared/utils/"),
27       },
28     },
29     performance: {
30       hints: false,
31     },
32     module: {
33       rules: [
34         {
35           test: /\.(scss|css)$/i,
36           use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
37         },
38         {
39           test: /\.(js|jsx|tsx|ts)$/, // All ts and tsx files will be process by
40           exclude: /node_modules/, // ignore node_modules
41           loader: "babel-loader",
42         },
43         // Due to some weird babel issue: https://github.com/webpack/webpack/issues/11467
44         {
45           test: /\.m?js/,
46           resolve: {
47             fullySpecified: false,
48           },
49         },
50       ],
51     },
52     plugins: [
53       new webpack.DefinePlugin({
54         "process.env.COMMIT_HASH": `"${env.COMMIT_HASH}"`,
55         "process.env.NODE_ENV": `"${mode}"`,
56       }),
57       new MiniCssExtractPlugin({
58         filename: "styles/styles.css",
59       }),
60       new CopyPlugin({
61         patterns: [{ from: "./src/assets", to: "./assets" }],
62       }),
63       new webpack.BannerPlugin({
64         banner,
65       }),
66     ],
67   };
68
69   const serverConfig = {
70     ...base,
71     entry: "./src/server/index.tsx",
72     output: {
73       ...base.output,
74       filename: "js/server.js",
75       publicPath: "/",
76     },
77     target: "node",
78     externals: [nodeExternals(), "inferno-helmet"],
79   };
80
81   const clientConfig = {
82     ...base,
83     entry: "./src/client/index.tsx",
84     output: {
85       ...base.output,
86       filename: "js/client.js",
87       publicPath: `/static/${env.COMMIT_HASH}/`,
88     },
89     plugins: [
90       ...base.plugins,
91       new ServiceWorkerPlugin({
92         enableInDevelopment: mode !== "development", // this may seem counterintuitive, but it is correct
93         workbox: {
94           cacheId: "lemmy",
95           include: [/(assets|styles|js)\/.+\..+$/g],
96           inlineWorkboxRuntime: true,
97           runtimeCaching: [
98             {
99               urlPattern: ({
100                 sameOrigin,
101                 url: { pathname, host },
102                 request: { method },
103               }) =>
104                 (sameOrigin || host.includes("localhost")) &&
105                 (!(
106                   pathname.includes("pictrs") || pathname.includes("static")
107                 ) ||
108                   method === "POST"),
109               handler: "NetworkFirst",
110               options: {
111                 cacheName: "instance-cache",
112               },
113             },
114             {
115               urlPattern: ({ url: { pathname, host }, sameOrigin }) =>
116                 (sameOrigin || host.includes("localhost")) &&
117                 pathname.includes("static"),
118               handler: mode === "development" ? "NetworkFirst" : "CacheFirst",
119               options: {
120                 cacheName: "static-cache",
121                 expiration: {
122                   maxAgeSeconds: 60 * 60 * 24,
123                 },
124               },
125             },
126             {
127               urlPattern: ({ url: { pathname }, request: { method } }) =>
128                 pathname.includes("pictrs") && method === "GET",
129               handler: "StaleWhileRevalidate",
130               options: {
131                 cacheName: "image-cache",
132                 expiration: {
133                   maxAgeSeconds: 60 * 60 * 24,
134                 },
135               },
136             },
137           ],
138         },
139       }),
140     ],
141   };
142
143   if (mode === "development") {
144     // serverConfig.cache = {
145     //   type: "filesystem",
146     //   name: "server",
147     // };
148
149     const RunNodeWebpackPlugin = require("run-node-webpack-plugin");
150     serverConfig.plugins.push(
151       new RunNodeWebpackPlugin({ runOnlyInWatchMode: true })
152     );
153   } else if (mode === "none") {
154     const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
155     serverConfig.plugins.push(new BundleAnalyzerPlugin());
156   }
157
158   return [serverConfig, clientConfig];
159 };