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.

299 lines
10 KiB

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