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.

302 lines
7.3 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  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 BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
  7. const { CleanWebpackPlugin: CleanPlugin } = require('clean-webpack-plugin');
  8. const CircularDependencyPlugin = require('circular-dependency-plugin');
  9. const CspHtmlPlugin = require('csp-html-webpack-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. eslint: 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 => p.includes('container.ts'))) 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. exclude: /node_modules|\.d\.ts$/,
  91. test: /\.tsx?$/,
  92. use: {
  93. loader: 'ts-loader',
  94. options: {
  95. experimentalWatchApi: true,
  96. transpileOnly: true
  97. }
  98. }
  99. }
  100. ]
  101. },
  102. resolve: {
  103. extensions: ['.ts', '.tsx', '.js', '.jsx', '.json']
  104. },
  105. plugins: plugins,
  106. stats: {
  107. all: false,
  108. assets: true,
  109. builtAt: true,
  110. env: true,
  111. errors: true,
  112. timings: true,
  113. warnings: true
  114. }
  115. };
  116. }
  117. function getWebviewsConfig(env) {
  118. const clean = ['**/*'];
  119. if (env.optimizeImages) {
  120. console.log('Optimizing images (src/webviews/apps/images/settings/*.png)...');
  121. clean.push(path.resolve(__dirname, 'images/settings/*'));
  122. }
  123. const cspPolicy = {
  124. 'default-src': "'none'",
  125. 'img-src': ['vscode-resource:', 'https:', 'data:'],
  126. 'script-src': ['vscode-resource:', "'nonce-Z2l0bGVucy1ib290c3RyYXA='"],
  127. 'style-src': ['vscode-resource:']
  128. };
  129. if (!env.production) {
  130. cspPolicy['script-src'].push("'unsafe-eval'");
  131. }
  132. /**
  133. * @type any[]
  134. */
  135. const plugins = [
  136. new CleanPlugin({ cleanOnceBeforeBuildPatterns: clean }),
  137. new ForkTsCheckerPlugin({
  138. tsconfig: path.resolve(__dirname, 'tsconfig.webviews.json'),
  139. async: false,
  140. eslint: true
  141. }),
  142. new MiniCssExtractPlugin({
  143. filename: '[name].css'
  144. }),
  145. new HtmlPlugin({
  146. excludeAssets: [/.+-styles\.js/],
  147. excludeChunks: ['welcome'],
  148. template: 'settings/index.html',
  149. filename: path.resolve(__dirname, 'dist/webviews/settings.html'),
  150. inject: true,
  151. inlineSource: env.production ? '.css$' : undefined,
  152. cspPlugin: {
  153. enabled: true,
  154. policy: cspPolicy,
  155. nonceEnabled: {
  156. 'script-src': true,
  157. 'style-src': true
  158. }
  159. },
  160. minify: env.production
  161. ? {
  162. removeComments: true,
  163. collapseWhitespace: true,
  164. removeRedundantAttributes: false,
  165. useShortDoctype: true,
  166. removeEmptyAttributes: true,
  167. removeStyleLinkTypeAttributes: true,
  168. keepClosingSlash: true,
  169. minifyCSS: true
  170. }
  171. : false
  172. }),
  173. new HtmlPlugin({
  174. excludeAssets: [/.+-styles\.js/],
  175. excludeChunks: ['settings'],
  176. template: 'welcome/index.html',
  177. filename: path.resolve(__dirname, 'dist/webviews/welcome.html'),
  178. inject: true,
  179. inlineSource: env.production ? '.css$' : undefined,
  180. cspPlugin: {
  181. enabled: true,
  182. policy: cspPolicy,
  183. nonceEnabled: {
  184. 'script-src': true,
  185. 'style-src': true
  186. }
  187. },
  188. minify: env.production
  189. ? {
  190. removeComments: true,
  191. collapseWhitespace: true,
  192. removeRedundantAttributes: false,
  193. useShortDoctype: true,
  194. removeEmptyAttributes: true,
  195. removeStyleLinkTypeAttributes: true,
  196. keepClosingSlash: true,
  197. minifyCSS: true
  198. }
  199. : false
  200. }),
  201. new HtmlExcludeAssetsPlugin(),
  202. new CspHtmlPlugin(),
  203. new ImageminPlugin({
  204. disable: !env.optimizeImages,
  205. externalImages: {
  206. context: path.resolve(__dirname, 'src/webviews/apps/images'),
  207. sources: glob.sync('src/webviews/apps/images/settings/*.png'),
  208. destination: path.resolve(__dirname, 'images')
  209. },
  210. cacheFolder: path.resolve(__dirname, 'node_modules', '.cache', 'imagemin-webpack-plugin'),
  211. gifsicle: null,
  212. jpegtran: null,
  213. optipng: null,
  214. pngquant: {
  215. quality: '85-100',
  216. speed: env.production ? 1 : 10
  217. },
  218. svgo: null
  219. }),
  220. new HtmlInlineSourcePlugin()
  221. ];
  222. return {
  223. name: 'webviews',
  224. context: path.resolve(__dirname, 'src/webviews/apps'),
  225. entry: {
  226. 'main-styles': ['./scss/main.scss'],
  227. settings: ['./settings/index.ts'],
  228. welcome: ['./welcome/index.ts']
  229. },
  230. mode: env.production ? 'production' : 'development',
  231. devtool: env.production ? undefined : 'eval-source-map',
  232. output: {
  233. filename: '[name].js',
  234. path: path.resolve(__dirname, 'dist/webviews'),
  235. publicPath: '#{root}/dist/webviews/'
  236. },
  237. module: {
  238. rules: [
  239. {
  240. exclude: /node_modules|\.d\.ts$/,
  241. test: /\.tsx?$/,
  242. use: {
  243. loader: 'ts-loader',
  244. options: {
  245. configFile: 'tsconfig.webviews.json',
  246. transpileOnly: true
  247. }
  248. }
  249. },
  250. {
  251. test: /\.scss$/,
  252. use: [
  253. {
  254. loader: MiniCssExtractPlugin.loader
  255. },
  256. {
  257. loader: 'css-loader',
  258. options: {
  259. sourceMap: true,
  260. url: false
  261. }
  262. },
  263. {
  264. loader: 'sass-loader',
  265. options: {
  266. sourceMap: true
  267. }
  268. }
  269. ],
  270. exclude: /node_modules/
  271. }
  272. ]
  273. },
  274. resolve: {
  275. extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
  276. modules: [path.resolve(__dirname, 'src/webviews/apps'), 'node_modules']
  277. },
  278. plugins: plugins,
  279. stats: {
  280. all: false,
  281. assets: true,
  282. builtAt: true,
  283. env: true,
  284. errors: true,
  285. timings: true,
  286. warnings: true
  287. }
  288. };
  289. }