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