mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
168 lines
4.4 KiB
JavaScript
168 lines
4.4 KiB
JavaScript
import { createHash } from "crypto";
|
|
import micromatch from 'micromatch';
|
|
import { performance } from 'perf_hooks';
|
|
|
|
var fs = Plugin.fs;
|
|
var path = Plugin.path;
|
|
|
|
const DEBUG_CACHE = process.env.DEBUG_METEOR_POSTCSS_DEP_CACHE === 'true';
|
|
|
|
let postcssConfig;
|
|
let loaded = false;
|
|
|
|
const missingPostCssError = new Error([
|
|
'',
|
|
`The postcss npm package could not be found in your node_modules`,
|
|
'directory. Please run the following command to install it:',
|
|
' meteor npm install postcss@8',
|
|
'or disable postcss by removing the postcss config.',
|
|
'',
|
|
].join('\n'));
|
|
|
|
export async function loadPostCss() {
|
|
if (loaded) {
|
|
return { postcssConfig };
|
|
}
|
|
|
|
let loadConfig;
|
|
try {
|
|
loadConfig = require('postcss-load-config');
|
|
} catch (e) {
|
|
// The app doesn't have this package installed
|
|
// Assuming the app doesn't use PostCSS
|
|
loaded = true;
|
|
|
|
return {};
|
|
}
|
|
|
|
let config;
|
|
try {
|
|
config = await loadConfig({ meteor: true });
|
|
} catch (e) {
|
|
if (e.message.includes('No PostCSS Config found in')) {
|
|
// PostCSS is not used by this app
|
|
loaded = true;
|
|
|
|
return {};
|
|
}
|
|
|
|
if (e.message.includes('Cannot find module \'postcss\'')) {
|
|
return { error: missingPostCssError };
|
|
}
|
|
|
|
e.message = `While loading postcss config: ${e.message}`;
|
|
return {
|
|
error: e,
|
|
};
|
|
}
|
|
|
|
let postcss;
|
|
try {
|
|
postcss = require('postcss');
|
|
} catch (e) {
|
|
return { error: missingPostCssError };
|
|
}
|
|
|
|
const postcssVersion = require('postcss/package.json').version;
|
|
const major = parseInt(postcssVersion.split('.')[0], 10);
|
|
if (major !== 8) {
|
|
// TODO: should this just be a warning instead?
|
|
const error = new Error([
|
|
'',
|
|
`Found version ${postcssVersion} of postcss in your node_modules`,
|
|
'directory. standard-minifier-css is only compatible with',
|
|
'version 8 of PostCSS. Please restart Meteor after installing',
|
|
'a supported version of PostCSS',
|
|
'',
|
|
].join('\n'));
|
|
|
|
return { error };
|
|
}
|
|
|
|
loaded = true;
|
|
config.postcss = postcss;
|
|
postcssConfig = config;
|
|
|
|
return { postcssConfig };
|
|
}
|
|
|
|
export function usePostCss(file, postcssConfig) {
|
|
if (!postcssConfig) {
|
|
return false;
|
|
}
|
|
|
|
const excludedPackages = postcssConfig.options.excludedMeteorPackages || [];
|
|
const path = file.getPathInBundle();
|
|
|
|
const excluded = excludedPackages.some(name => {
|
|
return path.includes(`packages/${name.replace(':', '_')}`);
|
|
});
|
|
|
|
return !excluded;
|
|
}
|
|
|
|
export const watchAndHashDeps = Profile(
|
|
'watchAndHashDeps',
|
|
function (deps, hashAndWatchFile) {
|
|
const hash = createHash('sha1');
|
|
const globsByDir = Object.create(null);
|
|
let fileCount = 0;
|
|
let folderCount = 0;
|
|
let start = performance.now();
|
|
|
|
deps.forEach(dep => {
|
|
if (dep.type === 'dependency') {
|
|
fileCount += 1;
|
|
const fileHash = hashAndWatchFile(dep.file);
|
|
hash.update(fileHash).update('\0');
|
|
} else if (dep.type === 'dir-dependency') {
|
|
if (dep.dir in globsByDir) {
|
|
globsByDir[dep.dir].push(dep.glob || '**');
|
|
} else {
|
|
globsByDir[dep.dir] = [dep.glob || '**'];
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Object.entries(globsByDir).forEach(([parentDir, globs]) => {
|
|
const matchers = globs.map(glob => micromatch.matcher(glob));
|
|
|
|
function walk(relDir) {
|
|
const absDir = path.join(parentDir, relDir);
|
|
hash.update(absDir).update('\0');
|
|
folderCount += 1;
|
|
|
|
const entries = fs.readdirWithTypesSync(absDir);
|
|
for (const entry of entries) {
|
|
const relPath = path.join(relDir, entry.name);
|
|
|
|
if (entry.isFile() && matchers.some(isMatch => isMatch(relPath))) {
|
|
const absPath = path.join(absDir, entry.name);
|
|
fileCount += 1;
|
|
hash.update(hashAndWatchFile(absPath)).update('\0');
|
|
} else if (
|
|
entry.isDirectory() && entry.name !== 'node_modules' && entry.name !== '.meteor'
|
|
) {
|
|
walk(relPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
walk('./');
|
|
});
|
|
|
|
let digest = hash.digest('hex');
|
|
|
|
if (DEBUG_CACHE) {
|
|
console.log('--- PostCSS Cache Info ---');
|
|
console.log('Glob deps', JSON.stringify(globsByDir, null, 2));
|
|
console.log('File dep count', fileCount);
|
|
console.log('Walked folders', folderCount);
|
|
console.log('Created dep cache key in', performance.now() - start, 'ms');
|
|
console.log('--------------------------');
|
|
}
|
|
|
|
return digest;
|
|
});
|