您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

276 行
9.5 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. devtoolModuleFilenameTemplate: 'file:///[absolute-resource-path]'
  62. },
  63. optimization: {
  64. minimizer: [
  65. new TerserPlugin({
  66. cache: true,
  67. parallel: true,
  68. sourceMap: true,
  69. terserOptions: {
  70. ecma: 8,
  71. // Keep the class names otherwise @log won't provide a useful name
  72. keep_classnames: true,
  73. module: true
  74. }
  75. })
  76. ]
  77. },
  78. externals: {
  79. vscode: 'commonjs vscode'
  80. },
  81. module: {
  82. rules: [
  83. {
  84. test: /\.ts$/,
  85. enforce: 'pre',
  86. use: 'tslint-loader',
  87. exclude: /node_modules/
  88. },
  89. {
  90. test: /\.tsx?$/,
  91. use: 'ts-loader',
  92. exclude: /node_modules|\.d\.ts$/
  93. }
  94. ],
  95. // Removes `Critical dependency: the request of a dependency is an expression` from `./node_modules/vsls/vscode.js`
  96. exprContextRegExp: /^$/,
  97. exprContextCritical: false
  98. },
  99. resolve: {
  100. extensions: ['.ts', '.tsx', '.js', '.jsx']
  101. },
  102. plugins: plugins,
  103. stats: {
  104. all: false,
  105. assets: true,
  106. builtAt: true,
  107. env: true,
  108. errors: true,
  109. timings: true,
  110. warnings: true
  111. }
  112. };
  113. }
  114. function getUIConfig(env) {
  115. const clean = ['settings.html', 'welcome.html'];
  116. if (env.optimizeImages) {
  117. console.log('Optimizing images (src/ui/images/settings/*.png)...');
  118. clean.push('images/settings');
  119. }
  120. const plugins = [
  121. new CleanPlugin(clean, { verbose: false }),
  122. new MiniCssExtractPlugin({
  123. filename: '[name].css'
  124. }),
  125. new HtmlPlugin({
  126. excludeChunks: ['welcome'],
  127. template: 'settings/index.html',
  128. filename: path.resolve(__dirname, 'settings.html'),
  129. inject: true,
  130. inlineSource: env.production ? '.(js|css)$' : undefined,
  131. minify: env.production
  132. ? {
  133. removeComments: true,
  134. collapseWhitespace: true,
  135. removeRedundantAttributes: true,
  136. useShortDoctype: true,
  137. removeEmptyAttributes: true,
  138. removeStyleLinkTypeAttributes: true,
  139. keepClosingSlash: true,
  140. minifyCSS: true
  141. }
  142. : false
  143. }),
  144. new HtmlPlugin({
  145. excludeChunks: ['settings'],
  146. template: 'welcome/index.html',
  147. filename: path.resolve(__dirname, 'welcome.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 HtmlInlineSourcePlugin(),
  164. new ImageminPlugin({
  165. disable: !env.optimizeImages,
  166. externalImages: {
  167. context: path.resolve(__dirname, 'src/ui/images'),
  168. sources: glob.sync('src/ui/images/settings/*.png'),
  169. destination: path.resolve(__dirname, 'images')
  170. },
  171. cacheFolder: path.resolve(__dirname, '.cache-images'),
  172. gifsicle: null,
  173. jpegtran: null,
  174. optipng: null,
  175. pngquant: {
  176. quality: '85-100',
  177. speed: env.production ? 1 : 10
  178. },
  179. svgo: null
  180. })
  181. ];
  182. return {
  183. name: 'ui',
  184. context: path.resolve(__dirname, 'src/ui'),
  185. // This is ugly having main.scss on both bundles, but if it is added separately it will generate a js bundle :(
  186. entry: {
  187. settings: ['./settings/index.ts', './scss/main.scss'],
  188. welcome: ['./welcome/index.ts', './scss/main.scss']
  189. // main: ['./scss/main.scss']
  190. },
  191. mode: env.production ? 'production' : 'development',
  192. devtool: env.production ? undefined : 'eval-source-map',
  193. output: {
  194. filename: '[name].js',
  195. path: path.resolve(__dirname, 'dist/ui'),
  196. publicPath: '{{root}}/dist/ui/'
  197. },
  198. module: {
  199. rules: [
  200. {
  201. test: /\.ts$/,
  202. enforce: 'pre',
  203. use: [
  204. {
  205. loader: 'tslint-loader',
  206. options: {
  207. tsConfigFile: 'ui.tsconfig.json'
  208. }
  209. }
  210. ],
  211. exclude: /node_modules/
  212. },
  213. {
  214. test: /\.tsx?$/,
  215. use: {
  216. loader: 'ts-loader',
  217. options: {
  218. configFile: 'ui.tsconfig.json'
  219. }
  220. },
  221. exclude: /node_modules|\.d\.ts$/
  222. },
  223. {
  224. test: /\.scss$/,
  225. use: [
  226. {
  227. loader: MiniCssExtractPlugin.loader
  228. },
  229. {
  230. loader: 'css-loader',
  231. options: {
  232. sourceMap: true,
  233. url: false
  234. }
  235. },
  236. {
  237. loader: 'sass-loader',
  238. options: {
  239. sourceMap: true
  240. }
  241. }
  242. ],
  243. exclude: /node_modules/
  244. }
  245. ]
  246. },
  247. resolve: {
  248. extensions: ['.ts', '.tsx', '.js', '.jsx'],
  249. modules: [path.resolve(__dirname, 'src/ui'), 'node_modules']
  250. },
  251. plugins: plugins,
  252. stats: {
  253. all: false,
  254. assets: true,
  255. builtAt: true,
  256. env: true,
  257. errors: true,
  258. timings: true,
  259. warnings: true
  260. }
  261. };
  262. }