Merge pull request #140 from drapanjanas/auto-require
Auto-require: infer components in use-figwheel command
This commit is contained in:
commit
45712a7627
20
README.md
20
README.md
|
@ -224,12 +224,28 @@ And you want to use a component called 'some-library/Component':
|
|||
```clojure
|
||||
(def Component (js/require "some-library/Component"))
|
||||
```
|
||||
This would work when you do `lein prod-build` and run your app, but will fail when you run with Figwheel.
|
||||
This works fine when you do `lein prod-build` and run your app.
|
||||
|
||||
The React Native packager statically scans for all calls to `require` and prepares the required
|
||||
code to be available at runtime. But, dynamically loaded (by Figwheel) code bypasses this scan
|
||||
and therefore requiring the custom component fails.
|
||||
|
||||
To overcome this run `use-component`:
|
||||
In re-natal this is solved by adding all dependencies in index.*.js file which is scanned by React Native packager.
|
||||
|
||||
#### Using auto-require
|
||||
|
||||
To enable auto-require feature you have to run command:
|
||||
```
|
||||
$ re-natal enable-auto-require
|
||||
```
|
||||
From now on, command `use-figwheel` will scan for all required modules and generate index.*.js with all required dependencies.
|
||||
You will have to re-run `use-figwheel` command every time you use new modules via `(js/require "...")`
|
||||
|
||||
This feature is available since re-natal@0.7.0
|
||||
|
||||
#### Manually registering dependencies with use-component command
|
||||
|
||||
You can register a single dependency manually by running `use-component` command:
|
||||
```
|
||||
$ re-natal use-component some-library/Component
|
||||
```
|
||||
|
|
|
@ -33,6 +33,8 @@ ipAddressRx = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/i
|
|||
figwheelUrlRx = /ws:\/\/[0-9a-zA-Z\.]*:/g
|
||||
appDelegateRx = /http:\/\/[^:]+/g
|
||||
debugHostRx = /host]\s+\?:\s+@".*";/g
|
||||
namespaceRx = /\(ns\s+([A-Za-z0-9.-]+)/g
|
||||
jsRequireRx = /js\/require "(.+)"/g
|
||||
rnVersion = '0.47.1'
|
||||
rnWinVersion = '0.47.0-rc.5'
|
||||
rnPackagerPort = 8081
|
||||
|
@ -210,6 +212,7 @@ generateConfig = (interfaceName, projName) ->
|
|||
modules: []
|
||||
imageDirs: ["images"]
|
||||
platforms: {}
|
||||
autoRequire: true
|
||||
|
||||
for platform in platforms
|
||||
config.platforms[platform] =
|
||||
|
@ -680,13 +683,52 @@ updateIosRCTWebSocketExecutor = (iosHost) ->
|
|||
RCTWebSocketExecutorPath = "node_modules/react-native/Libraries/WebSocket/RCTWebSocketExecutor.m"
|
||||
edit RCTWebSocketExecutorPath, [[debugHostRx, "host] ?: @\"#{iosHost}\";"]]
|
||||
|
||||
platformOfNamespace = (ns) ->
|
||||
if ns?
|
||||
possiblePlatforms = Object.keys platformMeta
|
||||
p = possiblePlatforms.find((p) -> ns.indexOf(".#{p}") > 0);
|
||||
p ?= "common"
|
||||
|
||||
extractRequiresFromSourceFile = (file) ->
|
||||
content = fs.readFileSync(file, encoding: 'utf8')
|
||||
requires = []
|
||||
while match = namespaceRx.exec(content)
|
||||
ns = match[1]
|
||||
while match = jsRequireRx.exec(content)
|
||||
requires.push(match[1])
|
||||
|
||||
platform: platformOfNamespace(ns)
|
||||
requires: requires
|
||||
|
||||
buildRequireByPlatformMap = () ->
|
||||
onlyUserCljs = (item) -> fpath.extname(item.path) == '.cljs' and
|
||||
item.path.indexOf('/target/') < 0 # ignore target dir
|
||||
files = klawSync process.cwd(),
|
||||
nodir: true
|
||||
filter: onlyUserCljs
|
||||
filenames = files.map((o) -> o.path)
|
||||
extractedRequires = filenames.map(extractRequiresFromSourceFile)
|
||||
|
||||
extractedRequires.reduce((result, item) ->
|
||||
platform = item.platform
|
||||
if result[platform]?
|
||||
result[platform] = Array.from(new Set(item.requires.concat(result[platform])))
|
||||
else
|
||||
result[platform] = Array.from(new Set(item.requires))
|
||||
result
|
||||
, {})
|
||||
|
||||
platformModulesAndImages = (config, platform) ->
|
||||
images = scanImages(config.imageDirs).map (fname) -> './' + fname;
|
||||
modulesAndImages = config.modules.concat images;
|
||||
if typeof config.platforms[platform].modules is 'undefined'
|
||||
modulesAndImages
|
||||
if config.autoRequire? and config.autoRequire
|
||||
requires = buildRequireByPlatformMap()
|
||||
requires.common.concat(requires[platform])
|
||||
else
|
||||
modulesAndImages.concat(config.platforms[platform].modules)
|
||||
images = scanImages(config.imageDirs).map (fname) -> './' + fname;
|
||||
modulesAndImages = config.modules.concat images;
|
||||
if typeof config.platforms[platform].modules is 'undefined'
|
||||
modulesAndImages
|
||||
else
|
||||
modulesAndImages.concat(config.platforms[platform].modules)
|
||||
|
||||
generateDevScripts = () ->
|
||||
try
|
||||
|
@ -705,6 +747,9 @@ generateDevScripts = () ->
|
|||
for platform in platforms
|
||||
devHost[platform] = config.platforms[platform].host
|
||||
|
||||
if config.autoRequire? and config.autoRequire
|
||||
log 'Auto-require is enabled. Scanning for require() calls in *.cljs files...'
|
||||
|
||||
for platform in platforms
|
||||
moduleMap = generateRequireModulesCode(platformModulesAndImages(config, platform))
|
||||
fs.writeFileSync "index.#{platform}.js", "#{moduleMap}require('figwheel-bridge').withModules(modules).start('#{projName}','#{platform}','#{devHost[platform]}');"
|
||||
|
@ -801,30 +846,31 @@ useComponent = (name, platform) ->
|
|||
logErr message
|
||||
|
||||
inferComponents = () ->
|
||||
onlyUserCljs = (item) -> fpath.extname(item.path) == '.cljs' and
|
||||
item.path.indexOf('/target/') < 0 # ignore target dir
|
||||
jsRequire = /js\/require \"(.+)\"/g
|
||||
files = klawSync process.cwd(),
|
||||
nodir: true
|
||||
filter: onlyUserCljs
|
||||
filenames = files.map((o) -> o.path)
|
||||
contents = filenames.map((path) -> fs.readFileSync(path, encoding: 'utf8'))
|
||||
requiresByPlatform = buildRequireByPlatformMap()
|
||||
|
||||
allRequires = []
|
||||
for k,v of requiresByPlatform
|
||||
allRequires = Array.from(new Set(allRequires.concat(v)))
|
||||
|
||||
config = readConfig() # re-natal file
|
||||
requires = new Set()
|
||||
contents.forEach((text) ->
|
||||
while match = jsRequire.exec(text)
|
||||
requires.add(match[1]) if match[1].indexOf(config.imageDirs) < 0)
|
||||
|
||||
modules = new Set(config.modules)
|
||||
difference = new Set(Array.from(requires).filter((m) -> !modules.has(m)))
|
||||
difference = new Set(Array.from(allRequires).filter((m) -> !modules.has(m)))
|
||||
if(difference.size isnt 0)
|
||||
log "new component import found #{Array.from(difference)}"
|
||||
config.modules = Array.from(requires)
|
||||
config.modules = Array.from(allRequires)
|
||||
writeConfig(config)
|
||||
else
|
||||
log "no new component was imported, defaulting to #{Array.from(modules)}"
|
||||
|
||||
autoRequire = (enabled) ->
|
||||
config = readConfig()
|
||||
config.autoRequire = enabled
|
||||
writeConfig(config)
|
||||
if (enabled)
|
||||
log "Auto-Require feature is enabled in use-figwheel command"
|
||||
else
|
||||
log "Auto-Require feature is disabled in use-figwheel command"
|
||||
|
||||
cli._name = 're-natal'
|
||||
cli.version pkgJson.version
|
||||
|
||||
|
@ -902,6 +948,16 @@ cli.command 'enable-source-maps'
|
|||
.action () ->
|
||||
patchReactNativePackager()
|
||||
|
||||
cli.command 'enable-auto-require'
|
||||
.description 'enables source scanning for automatic required module resolution in use-figwheel command.'
|
||||
.action () ->
|
||||
autoRequire(true)
|
||||
|
||||
cli.command 'disable-auto-require'
|
||||
.description 'disables auto-require feature in use-figwheel command'
|
||||
.action () ->
|
||||
autoRequire(false)
|
||||
|
||||
cli.command 'copy-figwheel-bridge'
|
||||
.description 'copy figwheel-bridge.js into project'
|
||||
.action () ->
|
||||
|
|
Loading…
Reference in New Issue