@epublishing/grunt-epublishing 1.2.6 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/cli.js CHANGED
@@ -60,10 +60,12 @@ function printOptions(options) {
60
60
  /**
61
61
  * Run npm install in jade and jade child gem directories.
62
62
  * Installs packages from each gem's package.json (excluding site).
63
+ * Skips if package-lock.json hasn't changed since the last install.
63
64
  * @param {Object} config - Build configuration with paths
64
65
  * @param {Object} options - Build options
65
66
  */
66
67
  async function runNpmInstall(config, options) {
68
+ const crypto = require('crypto');
67
69
  const Resolver = require('@epublishing/jade-resolver');
68
70
  const paths = config.paths || {};
69
71
  // Build paths object with ONLY jade and jade child gem directories (absolute paths)
@@ -89,10 +91,25 @@ async function runNpmInstall(config, options) {
89
91
 
90
92
  for (const dir of dirs) {
91
93
  const basename = path.basename(dir);
94
+ const lockFile = path.join(dir, 'package-lock.json');
95
+ const hasLock = fs.existsSync(lockFile);
96
+ const stampFile = path.join(dir, 'node_modules', '.package-lock.installed');
97
+
98
+ // Skip reinstall if package-lock.json hasn't changed since last npm ci
99
+ if (hasLock && fs.existsSync(stampFile)) {
100
+ const currentHash = crypto.createHash('sha1').update(fs.readFileSync(lockFile)).digest('hex');
101
+ const stampHash = fs.readFileSync(stampFile, 'utf8').trim();
102
+ if (currentHash === stampHash) {
103
+ if (options.verbose) {
104
+ console.log(chalk.gray(` Skipping npm install in ${basename} (package-lock.json unchanged)`));
105
+ }
106
+ continue;
107
+ }
108
+ }
109
+
92
110
  const spinner = ora(`Installing npm modules in ${basename}...`).start();
93
111
 
94
112
  try {
95
- const hasLock = fs.existsSync(path.join(dir, 'package-lock.json'));
96
113
  const cmd = hasLock ? 'ci' : 'install';
97
114
  await new Promise((resolve, reject) => {
98
115
  const proc = spawn('npm', [cmd], {
@@ -114,6 +131,16 @@ async function runNpmInstall(config, options) {
114
131
  reject(err);
115
132
  });
116
133
  });
134
+
135
+ // Write stamp so we can skip next time if package-lock.json is unchanged
136
+ if (hasLock) {
137
+ try {
138
+ const hash = crypto.createHash('sha1').update(fs.readFileSync(lockFile)).digest('hex');
139
+ fs.writeFileSync(stampFile, hash + '\n');
140
+ } catch {
141
+ // Stamp write failure is non-fatal — we'll just reinstall next time
142
+ }
143
+ }
117
144
  } catch (err) {
118
145
  throw err;
119
146
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@epublishing/grunt-epublishing",
3
3
  "description": "Modern front-end build tools for ePublishing Jade and client sites.",
4
- "version": "1.2.6",
4
+ "version": "1.2.7",
5
5
  "homepage": "https://www.epublishing.com",
6
6
  "contributors": [
7
7
  {