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.

275 lines
9.2 KiB

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