cssUtils.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.recordCssImportChain = exports.getCssImportBoundaries = exports.cssImporteeMap = exports.cssImporterMap = exports.resolvePostcssOptions = exports.compileCss = exports.rewriteCssUrls = exports.isCSSRequest = exports.cssModuleRE = exports.cssPreprocessLangRE = exports.urlRE = void 0;
  7. const path_1 = __importDefault(require("path"));
  8. const chalk_1 = __importDefault(require("chalk"));
  9. const transformUtils_1 = require("./transformUtils");
  10. const pathUtils_1 = require("./pathUtils");
  11. const resolveVue_1 = require("./resolveVue");
  12. const hash_sum_1 = __importDefault(require("hash-sum"));
  13. exports.urlRE = /url\(\s*('[^']+'|"[^"]+"|[^'")]+)\s*\)/;
  14. exports.cssPreprocessLangRE = /\.(less|sass|scss|styl|stylus|postcss)$/;
  15. exports.cssModuleRE = /\.module\.(less|sass|scss|styl|stylus|postcss|css)$/;
  16. exports.isCSSRequest = (file) => file.endsWith('.css') || exports.cssPreprocessLangRE.test(file);
  17. function rewriteCssUrls(css, replacerOrBase) {
  18. let replacer;
  19. if (typeof replacerOrBase === 'string') {
  20. replacer = (rawUrl) => {
  21. return path_1.default.posix.resolve(path_1.default.posix.dirname(replacerOrBase), rawUrl);
  22. };
  23. }
  24. else {
  25. replacer = replacerOrBase;
  26. }
  27. return transformUtils_1.asyncReplace(css, exports.urlRE, async (match) => {
  28. let [matched, rawUrl] = match;
  29. let wrap = '';
  30. const first = rawUrl[0];
  31. if (first === `"` || first === `'`) {
  32. wrap = first;
  33. rawUrl = rawUrl.slice(1, -1);
  34. }
  35. if (pathUtils_1.isExternalUrl(rawUrl) ||
  36. rawUrl.startsWith('data:') ||
  37. rawUrl.startsWith('#')) {
  38. return matched;
  39. }
  40. return `url(${wrap}${await replacer(rawUrl)}${wrap})`;
  41. });
  42. }
  43. exports.rewriteCssUrls = rewriteCssUrls;
  44. async function compileCss(root, publicPath, { source, filename, scoped, vars, modules, preprocessLang, preprocessOptions = {}, modulesOptions = {} }, isBuild = false) {
  45. const id = hash_sum_1.default(publicPath);
  46. const postcssConfig = await loadPostcssConfig(root);
  47. const { compileStyleAsync } = resolveVue_1.resolveCompiler(root);
  48. if (publicPath.endsWith('.css') &&
  49. !modules &&
  50. !postcssConfig &&
  51. !isBuild &&
  52. !source.includes('@import')) {
  53. // no need to invoke compile for plain css if no postcss config is present
  54. return source;
  55. }
  56. const { options: postcssOptions, plugins: postcssPlugins } = await resolvePostcssOptions(root, isBuild);
  57. if (preprocessLang) {
  58. preprocessOptions = preprocessOptions[preprocessLang] || preprocessOptions;
  59. // include node_modules for imports by default
  60. switch (preprocessLang) {
  61. case 'scss':
  62. case 'sass':
  63. preprocessOptions = {
  64. includePaths: ['node_modules'],
  65. ...preprocessOptions
  66. };
  67. break;
  68. case 'less':
  69. case 'stylus':
  70. preprocessOptions = {
  71. paths: ['node_modules'],
  72. ...preprocessOptions
  73. };
  74. }
  75. }
  76. return await compileStyleAsync({
  77. source,
  78. filename,
  79. id: `data-v-${id}`,
  80. scoped,
  81. vars,
  82. modules,
  83. modulesOptions: {
  84. generateScopedName: `[local]_${id}`,
  85. localsConvention: 'camelCase',
  86. ...modulesOptions
  87. },
  88. preprocessLang,
  89. preprocessCustomRequire: (id) => require(pathUtils_1.resolveFrom(root, id)),
  90. preprocessOptions,
  91. postcssOptions,
  92. postcssPlugins
  93. });
  94. }
  95. exports.compileCss = compileCss;
  96. let cachedPostcssConfig;
  97. async function loadPostcssConfig(root) {
  98. if (cachedPostcssConfig !== undefined) {
  99. return cachedPostcssConfig;
  100. }
  101. try {
  102. const load = require('postcss-load-config');
  103. return (cachedPostcssConfig = await load({}, root));
  104. }
  105. catch (e) {
  106. if (!/No PostCSS Config found/.test(e.message)) {
  107. console.error(chalk_1.default.red(`[vite] Error loading postcss config:`));
  108. console.error(e);
  109. }
  110. return (cachedPostcssConfig = null);
  111. }
  112. }
  113. async function resolvePostcssOptions(root, isBuild) {
  114. const config = await loadPostcssConfig(root);
  115. const options = config && config.options;
  116. const plugins = config && config.plugins ? config.plugins.slice() : [];
  117. plugins.unshift(require('postcss-import')());
  118. if (isBuild) {
  119. plugins.push(require('postcss-discard-comments')({ removeAll: true }));
  120. }
  121. return {
  122. options,
  123. plugins
  124. };
  125. }
  126. exports.resolvePostcssOptions = resolvePostcssOptions;
  127. exports.cssImporterMap = new Map();
  128. exports.cssImporteeMap = new Map();
  129. function getCssImportBoundaries(filePath, boundaries = new Set()) {
  130. if (!exports.cssImporterMap.has(filePath)) {
  131. return boundaries;
  132. }
  133. const importers = exports.cssImporterMap.get(filePath);
  134. for (const importer of importers) {
  135. boundaries.add(importer);
  136. getCssImportBoundaries(importer, boundaries);
  137. }
  138. return boundaries;
  139. }
  140. exports.getCssImportBoundaries = getCssImportBoundaries;
  141. function recordCssImportChain(dependencies, filePath) {
  142. const preImportees = exports.cssImporteeMap.get(filePath);
  143. // if import code change, should removed unused previous importee
  144. if (preImportees) {
  145. for (const preImportee of preImportees) {
  146. if (!dependencies.has(preImportee)) {
  147. const importers = exports.cssImporterMap.get(preImportee);
  148. if (importers) {
  149. importers.delete(filePath);
  150. }
  151. }
  152. }
  153. }
  154. dependencies.forEach((dependency) => {
  155. if (exports.cssImporterMap.has(dependency)) {
  156. exports.cssImporterMap.get(dependency).add(filePath);
  157. }
  158. else {
  159. exports.cssImporterMap.set(dependency, new Set([filePath]));
  160. }
  161. });
  162. exports.cssImporteeMap.set(filePath, dependencies);
  163. }
  164. exports.recordCssImportChain = recordCssImportChain;
  165. //# sourceMappingURL=cssUtils.js.map