Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use :npm-deps false to speed up Figwheel startup #3932

Closed
dmitryn opened this issue Apr 19, 2018 · 6 comments · Fixed by #4064
Closed

Use :npm-deps false to speed up Figwheel startup #3932

dmitryn opened this issue Apr 19, 2018 · 6 comments · Fixed by #4064
Labels

Comments

@dmitryn
Copy link
Contributor

dmitryn commented Apr 19, 2018

Description

Latest version of ClojureScript supports :npm-deps false compiler option.
It might speed up Figwheel start by 20-45 seconds bhauman/lein-figwheel#678
https://twitter.com/mfikes/status/986040242997284865?s=09

Solution

Add npm-deps false compiler option to dev builds. Compile builds for ios and android. Check if it increases Figwheel perfomance.

Twitter
“If you have a ClojureScript project where there also just happens to be a node_modules directory sitting there that ClojureScript itself doesn’t actually use (for example for React Native), :npm-deps false will be your new best friend. (It saves me 20 to 45 seconds of startup.)”
@status-open-bounty
Copy link

status-open-bounty commented Apr 20, 2018

Balance: 0.000000 ETH
Tokens: SNT: 375.00
Contract address: 0xfda8e90578d0408f7d4f3e3f4dc3b469efa2e16c
Network: Mainnet
Paid to: endenwer
Visit https://openbounty.status.im to learn more.

@debragail
Copy link
Contributor

Can you post the current performance metrics and logs?

@debragail
Copy link
Contributor

@dmitryn
Copy link
Contributor Author

dmitryn commented Apr 25, 2018

I don't have one. It's actually in scope of this issue to collect and compare such metrics.

@debragail
Copy link
Contributor

It looks like you use he node_modules folder according to this file:

findSymlinkedModules.js.patch

/**

  • Copyright (c) 2015-present, Facebook, Inc.
  • All rights reserved.
  • This source code is licensed under the BSD-style license found in the
  • LICENSE file in the root directory of this source tree. An additional grant
  • of patent rights can be found in the PATENTS file in the same directory.
  • @Format
  • @flow
    */

const path = require('path');
const fs = require('fs');

/**

  • Find symlinked modules inside "node_modules."
  • Naively, we could just perform a depth-first search of all folders in
  • node_modules, recursing when we find a symlink.
  • We can be smarter than this due to our knowledge of how npm/Yarn lays out
  • "node_modules" / how tools that build on top of npm/Yarn (such as Lerna)
  • install dependencies.
  • Starting from a given root node_modules folder, this algorithm will look at
  • both the top level descendants of the node_modules folder or second level
  • descendants of folders that start with "@" (which indicates a scoped
  • package). If any of those folders is a symlink, it will recurse into the
  • link, and perform the same search in the linked folder.
  • The end result should be a list of all resolved module symlinks for a given
  • root.
    */
    module.exports = function findSymlinkedModules(
    projectRoot: string,
    ignoredRoots: Array = [],
    ) {
    const timeStart = Date.now();
    const nodeModuleRoot = path.join(projectRoot, 'node_modules');
    const resolvedSymlinks = findModuleSymlinks(nodeModuleRoot, [
    ...ignoredRoots,
    projectRoot,
    ]);
    const timeEnd = Date.now();

console.log(
Scanning folders for symlinks in ${nodeModuleRoot} (${timeEnd - timeStart}ms),
);

return resolvedSymlinks;
};

function findModuleSymlinks(
modulesPath: string,
ignoredPaths: Array = [],
): Array {
if (!fs.existsSync(modulesPath)) {
return [];
}

// Find module symlinks
const moduleFolders = fs.readdirSync(modulesPath);
const symlinks = moduleFolders.reduce((links, folderName) => {
const folderPath = path.join(modulesPath, folderName);
const maybeSymlinkPaths = [];
if (folderName.startsWith('@')) {
const scopedModuleFolders = fs.readdirSync(folderPath);
maybeSymlinkPaths.push(
...scopedModuleFolders.map(name => path.join(folderPath, name)),
);
} else {
maybeSymlinkPaths.push(folderPath);
}
return links.concat(resolveSymlinkPaths(maybeSymlinkPaths, ignoredPaths));
}, []);

// For any symlinks found, look in that modules node_modules directory
// and find any symlinked modules
const nestedSymlinks = symlinks.reduce(
(links, symlinkPath) =>
links.concat(
// We ignore any found symlinks or anything from the ignored list,
// to prevent infinite recursion
findModuleSymlinks(path.join(symlinkPath, 'node_modules'), [
...ignoredPaths,
...symlinks,
]),
),
[],
);

return [...new Set([...symlinks, ...nestedSymlinks])];
}

function resolveSymlinkPaths(maybeSymlinkPaths, ignoredPaths) {
return maybeSymlinkPaths.reduce((links, maybeSymlinkPath) => {
if (fs.lstatSync(maybeSymlinkPath).isSymbolicLink()) {
const resolved = path.resolve(
path.dirname(maybeSymlinkPath),
fs.readlinkSync(maybeSymlinkPath),
);
if (ignoredPaths.indexOf(resolved) === -1 && fs.existsSync(resolved)) {
links.push(resolved);
}
}
return links;
}, []);
}

@debragail
Copy link
Contributor

Also I don’t know react native tooling that well but it seems to be an issue with 16:

facebook/react-native#15371

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants