]> Untitled Git - lemmy-ui.git/blob - webpack.config.js
Add Security.txt (#1408)
[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       publicPath: "/static/",
100     },
101     plugins: [
102       ...base.plugins,
103       new ServiceWorkerPlugin({
104         enableInDevelopment: mode !== "development", // this may seem counterintuitive, but it is correct
105         workbox: {
106           modifyURLPrefix: {
107             "/": "/static/",
108           },
109           cacheId: "lemmy",
110           include: [/(assets|styles|js)\/.+\..+$/g],
111           inlineWorkboxRuntime: true,
112           runtimeCaching: [
113             {
114               urlPattern: ({
115                 sameOrigin,
116                 url: { pathname, host },
117                 request: { method },
118               }) =>
119                 (sameOrigin || host.includes("localhost")) &&
120                 (!(
121                   pathname.includes("pictrs") || pathname.includes("static")
122                 ) ||
123                   method === "POST"),
124               handler: "NetworkFirst",
125               options: {
126                 cacheName: "instance-cache",
127               },
128             },
129             {
130               urlPattern: ({ url: { pathname, host }, sameOrigin }) =>
131                 (sameOrigin || host.includes("localhost")) &&
132                 pathname.includes("static"),
133               handler: mode === "development" ? "NetworkFirst" : "CacheFirst",
134               options: {
135                 cacheName: "static-cache",
136                 expiration: {
137                   maxAgeSeconds: 60 * 60 * 24,
138                 },
139               },
140             },
141             {
142               urlPattern: ({ url: { pathname }, request: { method } }) =>
143                 pathname.includes("pictrs") && method === "GET",
144               handler: "StaleWhileRevalidate",
145               options: {
146                 cacheName: "image-cache",
147                 expiration: {
148                   maxAgeSeconds: 60 * 60 * 24,
149                 },
150               },
151             },
152           ],
153         },
154       }),
155     ],
156   });
157
158   if (mode === "none") {
159     const BundleAnalyzerPlugin =
160       require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
161     config.plugins.push(new BundleAnalyzerPlugin());
162   }
163
164   return config;
165 };
166
167 module.exports = (env, properties) => [
168   createServerConfig(env, properties.mode || "development"),
169   createClientConfig(env, properties.mode || "development"),
170 ];