Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

345 rader
8.7 KiB

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