Last active
January 10, 2018 11:38
-
-
Save syaau/180aa5d4fda89357a52c5445d9b35654 to your computer and use it in GitHub Desktop.
Painless react-native library development and testing with symlinks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Keep this file in the project root | |
* | |
* Overrides configuration for metro-bundler so that any | |
* symlinked library (npm link) is automatically added | |
* to project root (listened for changes). Also all the | |
* dependencies and peerDependencies are provided through | |
* `extraNodeModules` options (which is the main problem | |
* with symlinked libraries in react-native). | |
* | |
* Make sure you install the library first using npm install | |
* so that all the dependencies are available within the project | |
* node_modules, after that use npm link to link the library. | |
*/ | |
const fs = require('fs'); | |
const path = require('path'); | |
const pkg = require('./package.json'); | |
// Using arguments check for development mode | |
function isDevMode() { | |
const idx = process.argv.indexOf('--dev'); | |
if (idx === -1 || idx === process.argv.length - 1) { | |
// Dev mode is true by default | |
return true; | |
} | |
return process.argv[idx + 1].toLowerCase() !== 'false'; | |
} | |
function getKeys(obj) { | |
if (!obj) { | |
return []; | |
} | |
return Object.keys(obj); | |
} | |
// Get all the libraries that have been sym-linked | |
function getLinkedLibraries() { | |
return Object.keys(pkg.dependencies).reduce((res, lib) => { | |
const p = path.resolve('node_modules', lib); | |
if (fs.lstatSync(p).isSymbolicLink()) { | |
res.libs[lib] = fs.realpathSync(p); | |
// Make sure to remove the lib from dependents if already added | |
const pos = res.dependents.indexOf(lib); | |
if (pos >= -1) { | |
res.dependents.splice(pos, 1); | |
} | |
// Search for all the dependencies/peer-dependencies within the library | |
// and include them separately | |
const dPkg = JSON.parse(fs.readFileSync(path.resolve(p, 'package.json'))); | |
const d = getKeys(dPkg.dependencies).concat(getKeys(dPkg.peerDependencies)); | |
res.dependents = d.reduce((uniques, n) => { | |
// Don't include twice and don't inlucde the linked libraries as well | |
if (uniques.indexOf(n) === -1 && !res.libs[n]) { | |
uniques.push(n); | |
} | |
return uniques; | |
}, res.dependents); | |
} | |
return res; | |
}, { | |
libs: {}, | |
dependents: [], | |
}); | |
} | |
// We do not want to link the libraries in production mode | |
// Always use the library through npm or git. | |
// If you have a library that's only kept locally, it's | |
// a good idea to use npm pack and keep the release inside | |
// the project for production mode and use that release file | |
// as dependency. You could always use npm link in development | |
// mode. | |
const DEV = isDevMode(); | |
let config = {}; | |
if (DEV) { | |
const linked = getLinkedLibraries(); | |
const libraryRequiredModules = linked.dependents; | |
const libRoots = Object.keys(linked.libs).map(k => linked.libs[k]); | |
config = { | |
extraNodeModules: libraryRequiredModules.reduce((res, lib) => ({ | |
...res, | |
[lib]: path.resolve(__dirname, 'node_modules', lib), | |
}), {}), | |
getProjectRoots() { | |
return [ | |
path.resolve(__dirname), | |
...libRoots, | |
]; | |
}, | |
}; | |
} | |
module.exports = config; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment