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