Stylus 0.54: Recovering from a Failed Upgrade Due to Missing Import Errors
0 reputation · 16 Jan 2020, 18:20 UTC
0 reputation · 16 Jan 2020, 18:20 UTC
When upgrading to Stylus 0.54, the default import resolution now throws an error if a referenced file is missing. This change improves safety but can break automated pipelines that previously ignored missing imports. Additionally, the behavior around circular imports is still unresolved: the current release throws an error, but documentation does not guarantee whether future releases will warn or allow them. These changes create a precise goal: to restore a build after an upgrade failure while maintaining project stability.
Given the constraints of missing file errors, potential circular import crashes, and the lack of glob support in @require, what strategies can developers employ to mitigate the impact of missing imports during an upgrade? How can circular imports be detected and resolved before they trigger build failures? What is the recommended approach to preserve build stability when upgrading to Stylus 0.54 in a large project with many dependencies?
35275 reputation · 16 Jan 2020, 21:35 UTC
When stylus 0.54 throws a Missing file error, the build can be restored by temporarily installing a fallback importer that returns null for unresolved paths. This keeps the compiler happy while you audit the source.
// customImporter.js
module.exports = function (file, prev, done) {
try {
return { path: file, contents: require('fs').readFileSync(file, 'utf8') };
} catch (e) {
console.warn('Stylus missing import:', file);
return null; // allow compilation to continue
}
};
Run the compiler locally:
stylus -u customImporter.js src/main.styl -o dist
If the build succeeds, you have a working snapshot that can be committed while you investigate the missing files.
0.54 treats any circular import as an error. To pre‑empt this, build a dependency graph before the actual compile:
const stylus = require('stylus');
const fs = require('fs');
const path = require('path');
function buildGraph(entry) {
const graph = new Map();
function walk(file) {
if (graph.has(file)) return;
const content = fs.readFileSync(file, 'utf8');
const imports = content.match(/@import\s+['\"]([^'\"]+)['\"]/g) || [];
const deps = imports.map(im => path.resolve(path.dirname(file), im.replace(/\\.styl$/, '') + '.styl'));
graph.set(file, deps);
deps.forEach(walk);
}
walk(entry);
return graph;
}
function detectCycles(graph) {
const visited = new Set();
const stack = new Set();
const cycles = [];
function dfs(node) {
if (stack.has(node)) {
cycles.push([...stack, node]);
return;
}
if (visited.has(node)) return;
visited.add(node);
stack.add(node);
const deps = graph.get(node) || [];
deps.forEach(dfs);
stack.delete(node);
}
graph.forEach((_, node) => dfs(node));
return cycles;
}
const graph = buildGraph('src/main.styl');
const cycles = detectCycles(graph);
if (cycles.length) {
console.error('Circular import detected:', cycles);
process.exit(1);
}
Run this script in CI before the Stylus step. If any cycles are reported, refactor the involved files to remove the cycle (e.g., merge the modules or use mixin exports instead of imports).
stylus --strict in the final build step.Since @require no longer supports glob patterns, any plugin that expands them will still trigger missing‑file errors unless updated. If you rely on such a plugin, please confirm its current version and whether it handles missing files gracefully; otherwise, consider replacing it with explicit @import statements or a custom importer that expands globs before passing them to Stylus.
stylus -u customImporter.js src/main.styl -o dist – compile locally with fallback.node validateGraph.js – run the pre‑build validation script.stylus --strict src/main.styl -o dist – final build step that fails on any error.By temporarily suppressing missing‑file errors, pre‑building a dependency graph to catch cycles, and then tightening the build pipeline, you can recover from a 0.54 upgrade and preserve stability across a large codebase. Remember to remove any silent‑import fallbacks before merging into production.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.