]> Untitled Git - lemmy-ui.git/blob - webpack.config.js
Merge pull request #1504 from alectrocute/actually-last-issue-template-tweaks
[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 const banner = `
10   hash:[contentHash], chunkhash:[chunkhash], name:[name], filebase:[base], query:[query], file:[file]
11   Source code: https://github.com/LemmyNet/lemmy-ui
12   Created by dessalines
13   @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL v3.0
14   `;
15
16 const base = {
17   output: {
18     filename: "js/server.js",
19     publicPath: "/",
20     hashFunction: "xxhash64",
21   },
22   resolve: {
23     extensions: [".js", ".jsx", ".ts", ".tsx"],
24     alias: {
25       "@": path.resolve(__dirname, "src/"),
26       "@utils": path.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 MiniCssExtractPlugin({
54       filename: "styles/styles.css",
55     }),
56     new CopyPlugin({
57       patterns: [{ from: "./src/assets", to: "./assets" }],
58     }),
59     new webpack.BannerPlugin({
60       banner,
61     }),
62   ],
63 };
64
65 const createServerConfig = (_env, mode) => {
66   const config = merge({}, base, {
67     mode,
68     entry: "./src/server/index.tsx",
69     output: {
70       filename: "js/server.js",
71     },
72     target: "node",
73     externals: [nodeExternals(), "inferno-helmet"],
74   });
75
76   if (mode === "development") {
77     // config.cache = {
78     //   type: "filesystem",
79     //   name: "server",
80     // };
81
82     config.plugins.push(
83       new RunNodeWebpackPlugin({
84         runOnlyInWatchMode: true,
85       })
86     );
87   }
88
89   return config;
90 };
91
92 const createClientConfig = (_env, mode) => {
93   const config = merge({}, base, {
94     mode,
95     entry: "./src/client/index.tsx",
96     output: {
97       filename: "js/client.js",
98     },
99     plugins: [
100       ...base.plugins,
101       new ServiceWorkerPlugin({
102         enableInDevelopment: mode !== "development", // this may seem counterintuitive, but it is correct
103         workbox: {
104           modifyURLPrefix: {
105             "/": "/static/",
106           },
107           cacheId: "lemmy",
108           include: [/(assets|styles)\/.+\..+|client\.js$/g],
109           inlineWorkboxRuntime: true,
110           runtimeCaching: [
111             {
112               urlPattern: ({
113                 sameOrigin,
114                 url: { pathname, host },
115                 request: { method },
116               }) =>
117                 (sameOrigin || host.includes("localhost")) &&
118                 (!(
119                   pathname.includes("pictrs") || pathname.includes("static")
120                 ) ||
121                   method === "POST"),
122               handler: "NetworkFirst",
123               options: {
124                 cacheName: "instance-cache",
125               },
126             },
127             {
128               urlPattern: ({ url: { pathname, host }, sameOrigin }) =>
129                 (sameOrigin || host.includes("localhost")) &&
130                 pathname.includes("static"),
131               handler: mode === "development" ? "NetworkFirst" : "CacheFirst",
132               options: {
133                 cacheName: "static-cache",
134                 expiration: {
135                   maxAgeSeconds: 60 * 60 * 24,
136                 },
137               },
138             },
139             {
140               urlPattern: ({ url: { pathname }, request: { method } }) =>
141                 pathname.includes("pictrs") && method === "GET",
142               handler: "StaleWhileRevalidate",
143               options: {
144                 cacheName: "image-cache",
145                 expiration: {
146                   maxAgeSeconds: 60 * 60 * 24,
147                 },
148               },
149             },
150           ],
151         },
152       }),
153     ],
154   });
155
156   if (mode === "development") {
157     // config.cache = {
158     //   type: "filesystem",
159     //   name: "client",
160     // };
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 ];