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.

298 rader
10 KiB

  1. 'use strict';
  2. const fs = require('fs');
  3. const glob = require('glob');
  4. const path = require('path');
  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 = env.production || Boolean(env.optimizeImages);
  20. if (!env.optimizeImages && !fs.existsSync(path.resolve(__dirname, 'images/settings'))) {
  21. env.optimizeImages = true;
  22. }
  23. // TODO: Total and complete HACK until the following vsls issues are resolved
  24. // https://github.com/MicrosoftDocs/live-share/issues/1334 & https://github.com/MicrosoftDocs/live-share/issues/1335
  25. const vslsPatchRegex = /const liveShareApiVersion = require\(path\.join\(__dirname, 'package\.json'\)\)\.version;/;
  26. let vslsPath = path.resolve(__dirname, 'node_modules/vsls/package.json');
  27. if (fs.existsSync(vslsPath)) {
  28. const vsls = require(vslsPath);
  29. if (vsls.main === undefined) {
  30. console.log('Fixing vsls package; Adding missing main to package.json...');
  31. vsls.main = 'vscode.js';
  32. fs.writeFileSync(vslsPath, `${JSON.stringify(vsls, undefined, 4)}\n`, 'utf8');
  33. }
  34. vslsPath = path.resolve(__dirname, 'node_modules/vsls/vscode.js');
  35. if (fs.existsSync(vslsPath)) {
  36. let code = fs.readFileSync(vslsPath, 'utf8');
  37. if (vslsPatchRegex.test(code)) {
  38. console.log('Fixing vsls package; Removing version lookup...');
  39. code = code.replace(
  40. vslsPatchRegex,
  41. `const liveShareApiVersion = '${
  42. vsls.version
  43. }'; // require(path.join(__dirname, 'package.json')).version;`
  44. );
  45. fs.writeFileSync(vslsPath, code, 'utf8');
  46. }
  47. }
  48. }
  49. return [getExtensionConfig(env), getUIConfig(env)];
  50. };
  51. function getExtensionConfig(env) {
  52. const plugins = [new CleanPlugin(['dist'], { verbose: false }), new webpack.IgnorePlugin(/^spawn-sync$/)];
  53. if (env.analyzeDeps) {
  54. plugins.push(
  55. new CircularDependencyPlugin({
  56. cwd: __dirname,
  57. exclude: /node_modules/,
  58. failOnError: false,
  59. onDetected({ module: webpackModuleRecord, paths, compilation }) {
  60. if (paths.some(p => /container\.ts/.test(p))) return;
  61. compilation.warnings.push(new Error(paths.join(' -> ')));
  62. }
  63. })
  64. );
  65. }
  66. if (env.analyzeBundle) {
  67. plugins.push(new BundleAnalyzerPlugin());
  68. }
  69. return {
  70. name: 'extension',
  71. entry: './src/extension.ts',
  72. mode: env.production ? 'production' : 'development',
  73. target: 'node',
  74. node: {
  75. __dirname: false
  76. },
  77. devtool: 'source-map',
  78. output: {
  79. libraryTarget: 'commonjs2',
  80. filename: 'extension.js'
  81. },
  82. optimization: {
  83. minimizer: [
  84. new TerserPlugin({
  85. cache: true,
  86. parallel: true,
  87. sourceMap: true,
  88. terserOptions: {
  89. ecma: 8,
  90. // Keep the class names otherwise @log won't provide a useful name
  91. keep_classnames: true,
  92. module: true
  93. }
  94. })
  95. ]
  96. },
  97. externals: {
  98. vscode: 'commonjs vscode'
  99. },
  100. module: {
  101. rules: [
  102. {
  103. test: /\.ts$/,
  104. enforce: 'pre',
  105. use: 'tslint-loader',
  106. exclude: /node_modules/
  107. },
  108. {
  109. test: /\.tsx?$/,
  110. use: 'ts-loader',
  111. exclude: /node_modules|\.d\.ts$/
  112. }
  113. ],
  114. // Removes `Critical dependency: the request of a dependency is an expression` from `./node_modules/vsls/vscode.js`
  115. exprContextRegExp: /^$/,
  116. exprContextCritical: false
  117. },
  118. resolve: {
  119. extensions: ['.ts', '.tsx', '.js', '.jsx', '.json']
  120. },
  121. plugins: plugins,
  122. stats: {
  123. all: false,
  124. assets: true,
  125. builtAt: true,
  126. env: true,
  127. errors: true,
  128. timings: true,
  129. warnings: true
  130. }
  131. };
  132. }
  133. function getUIConfig(env) {
  134. const clean = ['settings.html', 'welcome.html'];
  135. if (env.optimizeImages) {
  136. console.log('Optimizing images (src/ui/images/settings/*.png)...');
  137. clean.push('images/settings');
  138. }
  139. const plugins = [
  140. new CleanPlugin(clean, { verbose: false }),
  141. new MiniCssExtractPlugin({
  142. filename: '[name].css'
  143. }),
  144. new HtmlPlugin({
  145. excludeChunks: ['welcome'],
  146. template: 'settings/index.html',
  147. filename: path.resolve(__dirname, 'settings.html'),
  148. inject: true,
  149. inlineSource: env.production ? '.(js|css)$' : undefined,
  150. minify: env.production
  151. ? {
  152. removeComments: true,
  153. collapseWhitespace: true,
  154. removeRedundantAttributes: true,
  155. useShortDoctype: true,
  156. removeEmptyAttributes: true,
  157. removeStyleLinkTypeAttributes: true,
  158. keepClosingSlash: true,
  159. minifyCSS: true
  160. }
  161. : false
  162. }),
  163. new HtmlPlugin({
  164. excludeChunks: ['settings'],
  165. template: 'welcome/index.html',
  166. filename: path.resolve(__dirname, 'welcome.html'),
  167. inject: true,
  168. inlineSource: env.production ? '.(js|css)$' : undefined,
  169. minify: env.production
  170. ? {
  171. removeComments: true,
  172. collapseWhitespace: true,
  173. removeRedundantAttributes: true,
  174. useShortDoctype: true,
  175. removeEmptyAttributes: true,
  176. removeStyleLinkTypeAttributes: true,
  177. keepClosingSlash: true,
  178. minifyCSS: true
  179. }
  180. : false
  181. }),
  182. new HtmlInlineSourcePlugin(),
  183. new ImageminPlugin({
  184. disable: !env.optimizeImages,
  185. externalImages: {
  186. context: path.resolve(__dirname, 'src/ui/images'),
  187. sources: glob.sync('src/ui/images/settings/*.png'),
  188. destination: path.resolve(__dirname, 'images')
  189. },
  190. cacheFolder: path.resolve(__dirname, '.cache-images'),
  191. gifsicle: null,
  192. jpegtran: null,
  193. optipng: null,
  194. pngquant: {
  195. quality: '85-100',
  196. speed: env.production ? 1 : 10
  197. },
  198. svgo: null
  199. })
  200. ];
  201. return {
  202. name: 'ui',
  203. context: path.resolve(__dirname, 'src/ui'),
  204. // This is ugly having main.scss on both bundles, but if it is added separately it will generate a js bundle :(
  205. entry: {
  206. settings: ['./settings/index.ts', './scss/main.scss'],
  207. welcome: ['./welcome/index.ts', './scss/main.scss']
  208. // main: ['./scss/main.scss']
  209. },
  210. mode: env.production ? 'production' : 'development',
  211. devtool: env.production ? undefined : 'eval-source-map',
  212. output: {
  213. filename: '[name].js',
  214. path: path.resolve(__dirname, 'dist/ui'),
  215. publicPath: '{{root}}/dist/ui/'
  216. },
  217. module: {
  218. rules: [
  219. {
  220. test: /\.ts$/,
  221. enforce: 'pre',
  222. use: [
  223. {
  224. loader: 'tslint-loader',
  225. options: {
  226. tsConfigFile: 'ui.tsconfig.json'
  227. }
  228. }
  229. ],
  230. exclude: /node_modules/
  231. },
  232. {
  233. test: /\.tsx?$/,
  234. use: {
  235. loader: 'ts-loader',
  236. options: {
  237. configFile: 'ui.tsconfig.json'
  238. }
  239. },
  240. exclude: /node_modules|\.d\.ts$/
  241. },
  242. {
  243. test: /\.scss$/,
  244. use: [
  245. {
  246. loader: MiniCssExtractPlugin.loader
  247. },
  248. {
  249. loader: 'css-loader',
  250. options: {
  251. sourceMap: true,
  252. url: false
  253. }
  254. },
  255. {
  256. loader: 'sass-loader',
  257. options: {
  258. sourceMap: true
  259. }
  260. }
  261. ],
  262. exclude: /node_modules/
  263. }
  264. ]
  265. },
  266. resolve: {
  267. extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
  268. modules: [path.resolve(__dirname, 'src/ui'), 'node_modules']
  269. },
  270. plugins: plugins,
  271. stats: {
  272. all: false,
  273. assets: true,
  274. builtAt: true,
  275. env: true,
  276. errors: true,
  277. timings: true,
  278. warnings: true
  279. }
  280. };
  281. }