Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

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