You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

287 line
9.5 KiB

  1. 'use strict';
  2. const fs = require('fs');
  3. const glob = require('glob');
  4. const path = require('path');
  5. const webpack = require('webpack');
  6. const CleanPlugin = require('clean-webpack-plugin');
  7. const FileManagerPlugin = require('filemanager-webpack-plugin');
  8. const HtmlInlineSourcePlugin = require('html-webpack-inline-source-plugin');
  9. const HtmlPlugin = require('html-webpack-plugin');
  10. const ImageminPlugin = require('imagemin-webpack-plugin').default;
  11. const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  12. const TerserPlugin = require('terser-webpack-plugin');
  13. module.exports = function(env, argv) {
  14. env = env || {};
  15. env.production = Boolean(env.production);
  16. env.optimizeImages = env.production || Boolean(env.optimizeImages);
  17. env.copyClipboardyFallbacks = env.production || Boolean(env.copyClipboardyFallbacks);
  18. if (!env.optimizeImages && !fs.existsSync(path.resolve(__dirname, 'images/settings'))) {
  19. env.optimizeImages = true;
  20. }
  21. if (!env.copyClipboardyFallbacks && !fs.existsSync(path.resolve(__dirname, 'fallbacks'))) {
  22. env.copyClipboardyFallbacks = true;
  23. }
  24. return [getExtensionConfig(env), getUIConfig(env)];
  25. };
  26. function getExtensionConfig(env) {
  27. const clean = ['dist'];
  28. if (env.copyClipboardyFallbacks) {
  29. clean.push('fallbacks');
  30. }
  31. const plugins = [new CleanPlugin(clean, { verbose: false }), new webpack.IgnorePlugin(/^spawn-sync$/)];
  32. if (env.copyClipboardyFallbacks) {
  33. plugins.push(
  34. // @ts-ignore
  35. new FileManagerPlugin({
  36. onEnd: [
  37. {
  38. copy: [
  39. {
  40. source: path.resolve(__dirname, 'node_modules/clipboardy/fallbacks'),
  41. destination: 'fallbacks/'
  42. }
  43. ]
  44. }
  45. ]
  46. })
  47. );
  48. }
  49. return {
  50. name: 'extension',
  51. entry: './src/extension.ts',
  52. mode: env.production ? 'production' : 'development',
  53. target: 'node',
  54. node: {
  55. __dirname: false
  56. },
  57. devtool: 'source-map', //!env.production ? 'source-map' : undefined,
  58. output: {
  59. libraryTarget: 'commonjs2',
  60. filename: 'extension.js',
  61. devtoolModuleFilenameTemplate: 'file:///[absolute-resource-path]'
  62. },
  63. optimization: {
  64. minimizer: [
  65. new TerserPlugin({
  66. cache: true,
  67. parallel: true,
  68. sourceMap: true, // !env.production,
  69. terserOptions: {
  70. ecma: 8,
  71. // Keep the class names otherwise @log won't provide a useful name
  72. keep_classnames: true,
  73. module: true
  74. }
  75. })
  76. ]
  77. },
  78. externals: {
  79. vscode: 'commonjs vscode'
  80. },
  81. module: {
  82. rules: [
  83. {
  84. test: /\.ts$/,
  85. enforce: 'pre',
  86. use: 'tslint-loader',
  87. exclude: /node_modules/
  88. },
  89. {
  90. test: /\.tsx?$/,
  91. use: 'ts-loader',
  92. exclude: /node_modules|\.d\.ts$/
  93. }
  94. ],
  95. // Removes `Critical dependency: the request of a dependency is an expression` from `./node_modules/vsls/vscode.js`
  96. exprContextRegExp: /^$/,
  97. exprContextCritical: false
  98. },
  99. resolve: {
  100. extensions: ['.ts', '.tsx', '.js', '.jsx']
  101. },
  102. plugins: plugins,
  103. stats: {
  104. all: false,
  105. assets: true,
  106. builtAt: true,
  107. env: true,
  108. errors: true,
  109. timings: true,
  110. warnings: true
  111. }
  112. };
  113. }
  114. function getUIConfig(env) {
  115. const clean = ['settings.html', 'welcome.html'];
  116. if (env.optimizeImages) {
  117. console.log('Optimizing images (src/ui/images/settings/*.png)...');
  118. clean.push('images/settings');
  119. }
  120. const plugins = [
  121. new CleanPlugin(clean, { verbose: false }),
  122. new MiniCssExtractPlugin({
  123. filename: '[name].css'
  124. }),
  125. new HtmlPlugin({
  126. excludeAssets: [/.*\.main\.js/],
  127. excludeChunks: ['welcome'],
  128. template: 'settings/index.html',
  129. filename: path.resolve(__dirname, 'settings.html'),
  130. inject: true,
  131. inlineSource: env.production ? '.(js|css)$' : undefined,
  132. minify: env.production
  133. ? {
  134. removeComments: true,
  135. collapseWhitespace: true,
  136. removeRedundantAttributes: true,
  137. useShortDoctype: true,
  138. removeEmptyAttributes: true,
  139. removeStyleLinkTypeAttributes: true,
  140. keepClosingSlash: true,
  141. minifyCSS: true
  142. }
  143. : false
  144. }),
  145. new HtmlPlugin({
  146. excludeAssets: [/.*\.main\.js/],
  147. excludeChunks: ['settings'],
  148. template: 'welcome/index.html',
  149. filename: path.resolve(__dirname, 'welcome.html'),
  150. inject: true,
  151. inlineSource: env.production ? '.(js|css)$' : undefined,
  152. minify: env.production
  153. ? {
  154. removeComments: true,
  155. collapseWhitespace: true,
  156. removeRedundantAttributes: true,
  157. useShortDoctype: true,
  158. removeEmptyAttributes: true,
  159. removeStyleLinkTypeAttributes: true,
  160. keepClosingSlash: true,
  161. minifyCSS: true
  162. }
  163. : false
  164. }),
  165. new HtmlInlineSourcePlugin(),
  166. new ImageminPlugin({
  167. disable: !env.optimizeImages,
  168. externalImages: {
  169. context: path.resolve(__dirname, 'src/ui/images'),
  170. sources: glob.sync('src/ui/images/settings/*.png'),
  171. destination: path.resolve(__dirname, 'images')
  172. },
  173. cacheFolder: path.resolve(__dirname, '.cache-images'),
  174. gifsicle: null,
  175. jpegtran: null,
  176. optipng: null,
  177. pngquant: {
  178. quality: '85-100',
  179. speed: env.production ? 1 : 10
  180. },
  181. svgo: null
  182. })
  183. ];
  184. return {
  185. name: 'ui',
  186. context: path.resolve(__dirname, 'src/ui'),
  187. // This is ugly having main.scss on both bundles, but if it is added separately it will generate a js bundle :(
  188. entry: {
  189. settings: ['./settings/index.ts', './scss/main.scss'],
  190. welcome: ['./welcome/index.ts', './scss/main.scss']
  191. // main: ['./scss/main.scss']
  192. },
  193. mode: env.production ? 'production' : 'development',
  194. devtool: !env.production ? 'source-map' : undefined,
  195. output: {
  196. filename: '[name].js',
  197. path: path.resolve(__dirname, 'dist/ui'),
  198. publicPath: '{{root}}/dist/ui/'
  199. },
  200. optimization: {
  201. splitChunks: {
  202. cacheGroups: {
  203. styles: {
  204. name: 'styles',
  205. test: /\.css$/,
  206. chunks: 'all',
  207. enforce: true
  208. }
  209. }
  210. }
  211. },
  212. module: {
  213. rules: [
  214. {
  215. test: /\.ts$/,
  216. enforce: 'pre',
  217. use: [
  218. {
  219. loader: 'tslint-loader',
  220. options: {
  221. tsConfigFile: 'ui.tsconfig.json'
  222. }
  223. }
  224. ],
  225. exclude: /node_modules/
  226. },
  227. {
  228. test: /\.tsx?$/,
  229. use: {
  230. loader: 'ts-loader',
  231. options: {
  232. configFile: 'ui.tsconfig.json'
  233. }
  234. },
  235. exclude: /node_modules|\.d\.ts$/
  236. },
  237. {
  238. test: /\.scss$/,
  239. use: [
  240. {
  241. loader: MiniCssExtractPlugin.loader
  242. },
  243. {
  244. loader: 'css-loader',
  245. options: {
  246. sourceMap: !env.production,
  247. url: false
  248. }
  249. },
  250. {
  251. loader: 'sass-loader',
  252. options: {
  253. sourceMap: !env.production
  254. }
  255. }
  256. ],
  257. exclude: /node_modules/
  258. }
  259. ]
  260. },
  261. resolve: {
  262. extensions: ['.ts', '.tsx', '.js', '.jsx'],
  263. modules: [path.resolve(__dirname, 'src/ui'), 'node_modules']
  264. },
  265. plugins: plugins,
  266. stats: {
  267. all: false,
  268. assets: true,
  269. builtAt: true,
  270. env: true,
  271. errors: true,
  272. timings: true,
  273. warnings: true
  274. }
  275. };
  276. }