webpack.config.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. var webpack = require('webpack'),
  2. path = require('path'),
  3. fileSystem = require('fs-extra'),
  4. env = require('./env'),
  5. CopyWebpackPlugin = require('copy-webpack-plugin'),
  6. HtmlWebpackPlugin = require('html-webpack-plugin'),
  7. TerserPlugin = require('terser-webpack-plugin');
  8. var { CleanWebpackPlugin } = require('clean-webpack-plugin');
  9. var ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
  10. var ReactRefreshTypeScript = require('react-refresh-typescript');
  11. const ASSET_PATH = process.env.ASSET_PATH || '/';
  12. var alias = {
  13. '@': path.resolve(__dirname, 'src'),
  14. };
  15. // load the secrets
  16. var secretsPath = path.join(__dirname, 'secrets.' + env.NODE_ENV + '.js');
  17. var fileExtensions = [
  18. 'jpg',
  19. 'jpeg',
  20. 'png',
  21. 'gif',
  22. 'eot',
  23. 'otf',
  24. 'svg',
  25. 'ttf',
  26. 'woff',
  27. 'woff2',
  28. ];
  29. if (fileSystem.existsSync(secretsPath)) {
  30. alias['secrets'] = secretsPath;
  31. }
  32. const isDevelopment = process.env.NODE_ENV !== 'production';
  33. var options = {
  34. mode: process.env.NODE_ENV || 'development',
  35. entry: {
  36. newtab: path.join(__dirname, 'src', 'pages', 'Newtab', 'index.jsx'),
  37. options: path.join(__dirname, 'src', 'pages', 'Options', 'index.jsx'),
  38. popup: path.join(__dirname, 'src', 'pages', 'Popup', 'index.jsx'),
  39. background: path.join(__dirname, 'src', 'pages', 'Background', 'index.js'),
  40. contentScript: path.join(__dirname, 'src', 'pages', 'Content', 'index.js'),
  41. devtools: path.join(__dirname, 'src', 'pages', 'Devtools', 'index.js'),
  42. panel: path.join(__dirname, 'src', 'pages', 'Panel', 'index.jsx'),
  43. sidePanel: path.join(__dirname, 'src', 'pages', 'SidePanel', 'index.jsx'),
  44. },
  45. chromeExtensionBoilerplate: {
  46. notHotReload: ['background', 'contentScript', 'devtools'],
  47. },
  48. output: {
  49. filename: '[name].bundle.js',
  50. path: path.resolve(__dirname, 'build'),
  51. clean: true,
  52. publicPath: ASSET_PATH,
  53. },
  54. module: {
  55. rules: [
  56. {
  57. // look for .css or .scss files
  58. test: /\.(css|scss)$/,
  59. // in the `src` directory
  60. use: [
  61. {
  62. loader: 'style-loader',
  63. },
  64. {
  65. loader: 'css-loader',
  66. },
  67. {
  68. loader: 'postcss-loader',
  69. },
  70. {
  71. loader: 'sass-loader',
  72. options: {
  73. sourceMap: true,
  74. },
  75. },
  76. ],
  77. },
  78. {
  79. test: new RegExp('.(' + fileExtensions.join('|') + ')$'),
  80. type: 'asset/resource',
  81. exclude: /node_modules/,
  82. // loader: 'file-loader',
  83. // options: {
  84. // name: '[name].[ext]',
  85. // },
  86. },
  87. {
  88. test: /\.html$/,
  89. loader: 'html-loader',
  90. exclude: /node_modules/,
  91. },
  92. {
  93. test: /\.(ts|tsx)$/,
  94. exclude: /node_modules/,
  95. use: [
  96. {
  97. loader: require.resolve('ts-loader'),
  98. options: {
  99. getCustomTransformers: () => ({
  100. before: [isDevelopment && ReactRefreshTypeScript()].filter(
  101. Boolean
  102. ),
  103. }),
  104. transpileOnly: isDevelopment,
  105. },
  106. },
  107. ],
  108. },
  109. {
  110. test: /\.(js|jsx)$/,
  111. use: [
  112. {
  113. loader: 'source-map-loader',
  114. },
  115. {
  116. loader: require.resolve('babel-loader'),
  117. options: {
  118. plugins: [
  119. isDevelopment && require.resolve('react-refresh/babel'),
  120. ].filter(Boolean),
  121. },
  122. },
  123. ],
  124. exclude: /node_modules/,
  125. },
  126. ],
  127. },
  128. resolve: {
  129. alias: alias,
  130. extensions: fileExtensions
  131. .map((extension) => '.' + extension)
  132. .concat(['.js', '.jsx', '.ts', '.tsx', '.css']),
  133. },
  134. plugins: [
  135. isDevelopment && new ReactRefreshWebpackPlugin(),
  136. new CleanWebpackPlugin({ verbose: false }),
  137. new webpack.ProgressPlugin(),
  138. // expose and write the allowed env vars on the compiled bundle
  139. new webpack.EnvironmentPlugin(['NODE_ENV']),
  140. new CopyWebpackPlugin({
  141. patterns: [
  142. {
  143. from: 'src/manifest.json',
  144. to: path.join(__dirname, 'build'),
  145. force: true,
  146. transform: function (content, path) {
  147. // generates the manifest file using the package.json informations
  148. return Buffer.from(
  149. JSON.stringify({
  150. description: process.env.npm_package_description,
  151. version: process.env.npm_package_version,
  152. ...JSON.parse(content.toString()),
  153. })
  154. );
  155. },
  156. },
  157. ],
  158. }),
  159. new CopyWebpackPlugin({
  160. patterns: [
  161. {
  162. from: 'src/pages/Content/content.styles.css',
  163. to: path.join(__dirname, 'build'),
  164. force: true,
  165. },
  166. ],
  167. }),
  168. new CopyWebpackPlugin({
  169. patterns: [
  170. {
  171. from: 'src/assets/img/icon-128.png',
  172. to: path.join(__dirname, 'build'),
  173. force: true,
  174. },
  175. ],
  176. }),
  177. new CopyWebpackPlugin({
  178. patterns: [
  179. {
  180. from: 'src/assets/img/icon-34.png',
  181. to: path.join(__dirname, 'build'),
  182. force: true,
  183. },
  184. ],
  185. }),
  186. new HtmlWebpackPlugin({
  187. template: path.join(__dirname, 'src', 'pages', 'Newtab', 'index.html'),
  188. filename: 'newtab.html',
  189. chunks: ['newtab'],
  190. cache: false,
  191. }),
  192. new HtmlWebpackPlugin({
  193. template: path.join(__dirname, 'src', 'pages', 'Options', 'index.html'),
  194. filename: 'options.html',
  195. chunks: ['options'],
  196. cache: false,
  197. }),
  198. new HtmlWebpackPlugin({
  199. template: path.join(__dirname, 'src', 'pages', 'Popup', 'index.html'),
  200. filename: 'popup.html',
  201. chunks: ['popup'],
  202. cache: false,
  203. }),
  204. new HtmlWebpackPlugin({
  205. template: path.join(__dirname, 'src', 'pages', 'Devtools', 'index.html'),
  206. filename: 'devtools.html',
  207. chunks: ['devtools'],
  208. cache: false,
  209. }),
  210. new HtmlWebpackPlugin({
  211. template: path.join(__dirname, 'src', 'pages', 'Panel', 'index.html'),
  212. filename: 'panel.html',
  213. chunks: ['panel'],
  214. cache: false,
  215. }),
  216. new HtmlWebpackPlugin({
  217. template: path.join(__dirname, 'src', 'pages', 'SidePanel', 'index.html'),
  218. filename: 'sidePanel.html',
  219. chunks: ['sidePanel'],
  220. cache: false,
  221. }),
  222. ].filter(Boolean),
  223. infrastructureLogging: {
  224. level: 'info',
  225. },
  226. };
  227. if (env.NODE_ENV === 'development') {
  228. options.devtool = 'cheap-module-source-map';
  229. } else {
  230. options.optimization = {
  231. minimize: true,
  232. minimizer: [
  233. new TerserPlugin({
  234. extractComments: false,
  235. }),
  236. ],
  237. };
  238. }
  239. module.exports = options;