webpack.common.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // @flow
  2. const path = require('path');
  3. const TerserPlugin = require('terser-webpack-plugin');
  4. const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  5. const browserslist = require('browserslist')();
  6. const caniuse = require('caniuse-lite');
  7. // from the least supported to the most supported
  8. const fonts = ['woff2', 'woff', 'ttf'];
  9. /*::
  10. type Target = {|
  11. name: string, // the name of output JS/CSS
  12. entry: string, // the path to the entry point
  13. library?: string // the name of the exported module
  14. |};
  15. */
  16. /**
  17. * List of targets to build
  18. */
  19. const targets /*: Array<Target> */ = [
  20. {
  21. name: 'katex',
  22. entry: './katex.webpack.js',
  23. library: 'katex',
  24. },
  25. {
  26. name: 'contrib/auto-render',
  27. entry: './contrib/auto-render/auto-render.js',
  28. library: 'renderMathInElement',
  29. },
  30. {
  31. name: 'contrib/mhchem',
  32. entry: './contrib/mhchem/mhchem.js',
  33. },
  34. {
  35. name: 'contrib/copy-tex',
  36. entry: './contrib/copy-tex/copy-tex.webpack.js',
  37. },
  38. {
  39. name: 'contrib/mathtex-script-type',
  40. entry: './contrib/mathtex-script-type/mathtex-script-type.js',
  41. },
  42. ];
  43. /**
  44. * Create a webpack config for given target
  45. */
  46. function createConfig(target /*: Target */, dev /*: boolean */,
  47. minimize /*: boolean */) /*: Object */ {
  48. const cssLoaders /*: Array<Object> */ = [{loader: 'css-loader'}];
  49. if (minimize) {
  50. cssLoaders[0].options = {importLoaders: 1};
  51. cssLoaders.push({
  52. loader: 'postcss-loader',
  53. options: {plugins: [require('cssnano')()]},
  54. });
  55. }
  56. // use only necessary fonts, overridable by environment variables
  57. const lessOptions = {modifyVars: {}};
  58. let isCovered = false;
  59. for (const font of fonts) {
  60. const override = process.env[`USE_${font.toUpperCase()}`];
  61. const useFont = override === "true" || override !== "false" && !isCovered;
  62. lessOptions.modifyVars[`use-${font}`] = useFont;
  63. const support = caniuse.feature(caniuse.features[font]).stats;
  64. isCovered = isCovered || useFont && browserslist.every(browser => {
  65. const [name, version] = browser.split(' ');
  66. return !support[name] || support[name][version] === 'y';
  67. });
  68. }
  69. return {
  70. mode: dev ? 'development' : 'production',
  71. context: __dirname,
  72. entry: {
  73. [target.name]: target.entry,
  74. },
  75. output: {
  76. filename: minimize ? '[name].min.js' : '[name].js',
  77. library: target.library,
  78. libraryTarget: 'umd',
  79. libraryExport: 'default',
  80. // Enable output modules to be used in browser or Node.
  81. // See: https://github.com/webpack/webpack/issues/6522
  82. globalObject: "(typeof self !== 'undefined' ? self : this)",
  83. path: path.resolve(__dirname, 'dist'),
  84. publicPath: dev ? '/' : '',
  85. },
  86. module: {
  87. rules: [
  88. {
  89. test: /\.js$/,
  90. exclude: /node_modules/,
  91. use: 'babel-loader',
  92. },
  93. {
  94. test: /\.css$/,
  95. use: [
  96. dev ? 'style-loader' : MiniCssExtractPlugin.loader,
  97. ...cssLoaders,
  98. ],
  99. },
  100. {
  101. test: /\.less$/,
  102. use: [
  103. dev ? 'style-loader' : MiniCssExtractPlugin.loader,
  104. ...cssLoaders,
  105. {
  106. loader: 'less-loader',
  107. options: lessOptions,
  108. },
  109. ],
  110. },
  111. {
  112. test: /\.(ttf|woff|woff2)$/,
  113. use: [{
  114. loader: 'file-loader',
  115. options: {
  116. name: 'fonts/[name].[ext]',
  117. },
  118. }],
  119. },
  120. ],
  121. },
  122. externals: 'katex',
  123. plugins: [
  124. !dev && new MiniCssExtractPlugin({
  125. filename: minimize ? '[name].min.css' : '[name].css',
  126. }),
  127. ].filter(Boolean),
  128. devtool: dev && 'inline-source-map',
  129. optimization: {
  130. minimize,
  131. minimizer: [
  132. new TerserPlugin({
  133. terserOptions: {
  134. output: {
  135. ascii_only: true,
  136. },
  137. },
  138. }),
  139. ],
  140. },
  141. performance: {
  142. hints: false,
  143. },
  144. };
  145. }
  146. module.exports = {
  147. targets,
  148. createConfig,
  149. };