Skip to content

Commit

Permalink
Make :preloads and :closure-defines work (#185)
Browse files Browse the repository at this point in the history
* using reagent 0.8.0-alpha1

* require react-native in namespace declaration

* bump versions

* make preloads and closure defines work

* make preloads and closure defines work

* revert changes in core.cljs

* do not preload cljs-devtools it causes a warning on startup

* add empty line

* update README

* code cleanup

* bump om-next version
  • Loading branch information
drapanjanas authored May 29, 2018
1 parent 845f4cd commit dac3e20
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 66 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ For more ClojureScript React Native resources visit [cljsrn.org](http://cljsrn.o
Contributions are very welcome.

## Status
- Uses [React Native] v0.53.0
- Uses [React Native] v0.55.4
- Reusable codebase between iOS and Android
- Figwheel used for REPL and live coding
- Works in iOS (real device and simulator)
Expand Down
16 changes: 6 additions & 10 deletions re-natal.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ ipAddressRx = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/i
debugHostRx = /host]\s+\?:\s+@".*";/g
namespaceRx = /\(ns\s+([A-Za-z0-9.-]+)/g
jsRequireRx = /js\/require "(.+)"/g
rnVersion = '0.53.0'
rnWinVersion = '0.53.0-rc.1'
rnVersion = '0.55.4'
rnWinVersion = '0.55.0-rc.0'
rnPackagerPort = 8081
process.title = 're-natal'
buildProfiles =
Expand Down Expand Up @@ -64,17 +64,17 @@ interfaceConf =
sources:
common: ["events.cljs", "subs.cljs", "db.cljs"]
other: [["reagent_dom.cljs","reagent/dom.cljs"], ["reagent_dom_server.cljs","reagent/dom/server.cljs"]]
deps: ['[reagent "0.7.0" :exclusions [cljsjs/react cljsjs/react-dom cljsjs/react-dom-server cljsjs/create-react-class]]'
'[re-frame "0.10.4"]']
shims: ["cljsjs.react", "cljsjs.react.dom", "cljsjs.react.dom.server", "cljsjs.create-react-class"]
deps: ['[reagent "0.8.1" :exclusions [cljsjs/react cljsjs/react-dom cljsjs/react-dom-server cljsjs/create-react-class]]'
'[re-frame "0.10.5"]']
shims: []
sampleCommandNs: '(in-ns \'$PROJECT_NAME_HYPHENATED$.ios.core)'
sampleCommand: '(dispatch [:set-greeting "Hello Native World!"])'
'om-next':
cljsDir: "cljs-om-next"
sources:
common: ["state.cljs"]
other: [["support.cljs","re_natal/support.cljs"]]
deps: ['[org.omcljs/om "1.0.0-beta1" :exclusions [cljsjs/react cljsjs/react-dom]]']
deps: ['[org.omcljs/om "1.0.0-beta3" :exclusions [cljsjs/react cljsjs/react-dom]]']
shims: ["cljsjs.react", "cljsjs.react.dom"]
sampleCommandNs: '(in-ns \'$PROJECT_NAME_HYPHENATED$.state)'
sampleCommand: '(swap! app-state assoc :app/msg "Hello Native World!")'
Expand Down Expand Up @@ -131,10 +131,6 @@ ensureExecutableAvailable = (executable) ->
exec "type #{executable}"

isYarnAvailable = () ->
try
ensureExecutableAvailable('yarn')
true
catch e
false

isSomeDepsMissing = () ->
Expand Down
1 change: 1 addition & 0 deletions resources/advanced.profile
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
:static-fns true
:optimize-constants true
:optimizations :advanced
:target :nodejs
:closure-defines {"goog.DEBUG" false}}}
5 changes: 3 additions & 2 deletions resources/dev.profile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{:id "$PLATFORM$"
:source-paths ["src" "env/dev"]
:figwheel true
:compiler {:output-to "target/$PLATFORM$/not-used.js"
:compiler {:output-to "target/$PLATFORM$/index.js"
:main "env.$PLATFORM$.main"
:output-dir "target/$PLATFORM$"
:optimizations :none}}
:optimizations :none
:target :nodejs}}
115 changes: 63 additions & 52 deletions resources/figwheel-bridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* @providesModule figwheel-bridge
*/

var CLOSURE_UNCOMPILED_DEFINES = null;
var debugEnabled = false;

var config = {
Expand Down Expand Up @@ -33,34 +32,34 @@ function formatCompileError(msg) {
var errorStr = "Figwheel Compile Exception: "
var data = msg['exception-data'];
if(data['message']) {
errorStr += data['message'] + " ";
errorStr += data['message'] + " ";
}
if(data['file']) {
errorStr += "in file " + data['file'] + " ";
errorStr += "in file " + data['file'] + " ";
}
if(data['line']) {
errorStr += "at line " + data['line'];
errorStr += "at line " + data['line'];
}
if(data['column']) {
errorStr += ", column " + data['column'];
errorStr += ", column " + data['column'];
}
return errorStr;
}

/* This is simply demonstrating that we can receive and react to
/* This is simply demonstrating that we can receive and react to
* arbitrary messages from Figwheel this will enable creating a nicer
* feedback system in the Figwheel top level React component.
*/
function figwheelMessageHandler(msg) {
if(msg["msg-name"] == "compile-failed") {
console.warn(formatCompileError(msg));
console.warn(formatCompileError(msg));
}
}

function listenToFigwheelMessages() {
if(figwheel.client.add_json_message_watch) {
figwheel.client.add_json_message_watch("ReactNativeMessageIntercept",
figwheelMessageHandler);
figwheel.client.add_json_message_watch("ReactNativeMessageIntercept",
figwheelMessageHandler);
}
}

Expand All @@ -86,7 +85,7 @@ var figwheelApp = function (platform, devHost) {
if (typeof goog === "undefined") {
loadApp(platform, devHost, function (appRoot) {
app.setState({root: appRoot, loaded: true});
listenToFigwheelMessages();
listenToFigwheelMessages();
});
}
}
Expand All @@ -103,34 +102,34 @@ var isChrome = function () {
return typeof importScripts === "function"
};

function asyncImportScripts(url, success, error) {
function asyncImportScripts(url, transform, success, error) {
logDebug('(asyncImportScripts) Importing: ' + url);
asyncImportChain =
asyncImportChain
.then(function (v) {return fetch(url);})
.then(function (response) {
if(response.ok)
return response.text();
throw new Error("Failed to Fetch: " + url + " - Perhaps your project was cleaned and you haven't recompiled?")
})
.then(function (responseText) {
evaluate(responseText);
fireEvalListenters(url);
success();
return true;
})
.catch(function (e) {
console.error(e);
error();
return true;
});
asyncImportChain
.then(function (v) {return fetch(url);})
.then(function (response) {
if(response.ok)
return response.text();
throw new Error("Failed to Fetch: " + url + " - Perhaps your project was cleaned and you haven't recompiled?")
})
.then(function (responseText) {
evaluate(transform(responseText));
fireEvalListenters(url);
success();
return true;
})
.catch(function (e) {
console.error(e);
error();
return true;
});
}

function syncImportScripts(url, success, error) {
try {
importScripts(url);
logDebug('Evaluated: ' + url);
fireEvalListenters(url);
fireEvalListenters(url);
success();
} catch (e) {
console.error(e);
Expand All @@ -141,13 +140,14 @@ function syncImportScripts(url, success, error) {
// Loads js file sync if possible or async.
function importJs(src, success, error) {
var noop = function(){};
success = (typeof success == 'function') ? success : noop;
error = (typeof error == 'function') ? error : noop;
var identity = function (arg){return arg};
var successCb = (typeof success == 'function') ? success : noop;
var errorCb = (typeof error == 'function') ? error : noop;
logDebug('(importJs) Importing: ' + src);
if (isChrome()) {
syncImportScripts(src, success, error);
syncImportScripts(src, successCb, errorCb);
} else {
asyncImportScripts(src, success, error);
asyncImportScripts(src, identity, successCb, errorCb);
}
}

Expand Down Expand Up @@ -175,16 +175,29 @@ function isUnDefined(x) {
function assertRootElExists(platform) {
var basicMessage = "ClojureScript project didn't compile, or didn't load correctly.";
if(isUnDefined(env)) {
throw new Error("Critical Error: env namespace not defined - " + basicMessage);
throw new Error("Critical Error: env namespace not defined - " + basicMessage);
} else if(isUnDefined(env[platform])) {
throw new Error("Critical Error: env." + platform + " namespace not defined - " + basicMessage);
throw new Error("Critical Error: env." + platform + " namespace not defined - " + basicMessage);
} else if(isUnDefined(env[platform].main)) {
throw new Error("Critical Error: env." + platform + ".main namespace not defined - " + basicMessage);
throw new Error("Critical Error: env." + platform + ".main namespace not defined - " + basicMessage);
} else if(isUnDefined(env[platform].main.root_el)) {
throw new Error("Critical Error: env." +
platform + ".main namespace doesn't define a root-el which should hold the root react node of your app.");
throw new Error("Critical Error: env." +
platform + ".main namespace doesn't define a root-el which should hold the root react node of your app.");
}
}
}

function importIndexJs(fileBasePath) {
var src = fileBasePath + '/index.js';
var transformFn = function(code) {
var defines = code.match(new RegExp ("goog.global.CLOSURE_UNCOMPILED_DEFINES.*?;"));
var deps = code.match(/goog.require\(.*?\);/g);
var transformedCode = defines.concat(deps).join('');
logDebug('transformed index.js: ', transformedCode);
return transformedCode;
};
logDebug('(importIndexJs) Importing: ' + src);
asyncImportScripts(src, transformFn, function(){}, function(){});
}

function loadApp(platform, devHost, onLoadCb) {
var fileBasePath = serverBaseUrl((isChrome() ? "localhost" : devHost)) + "/" + config.basePath + platform;
Expand All @@ -193,26 +206,24 @@ function loadApp(platform, devHost, onLoadCb) {
var mainJs = `/env/${platform}/main.js`;
evalListeners.waitForFinalEval = function (url) {
if (url.indexOf(mainJs) > -1) {
assertRootElExists(platform);
assertRootElExists(platform);
onLoadCb(env[platform].main.root_el);
console.info('Done loading Clojure app');
delete evalListeners.waitForFinalEval;
delete evalListeners.waitForFinalEval;
}
};

if (typeof goog === "undefined") {
console.info('Loading Closure base.');
interceptRequire();
// need to know base path here

// need to know base path here
importJs(fileBasePath + '/goog/base.js', function () {
shimBaseGoog(fileBasePath);
importJs(fileBasePath + '/cljs_deps.js');
importJs(fileBasePath + '/goog/deps.js', function () {
// This is needed because of RN packager
// seriously React packager? why.
var googreq = goog.require;

googreq(`env.${platform}.main`);
importJs(fileBasePath + '/cljs_deps.js', function () {
importJs(fileBasePath + '/goog/deps.js', function () {
importIndexJs(fileBasePath);
});
});
});
}
Expand All @@ -230,8 +241,8 @@ function withModules(moduleById) {

function figwheelImportScript(uri, callback) {
importJs(uri.toString(),
function () {callback(true);},
function () {callback(false);})
function () {callback(true);},
function () {callback(false);})
}

// Goog fixes
Expand Down
1 change: 1 addition & 0 deletions resources/prod.profile
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
:static-fns true
:optimize-constants true
:optimizations :simple
:target :nodejs
:closure-defines {"goog.DEBUG" false}}}
2 changes: 1 addition & 1 deletion resources/project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.9.0"]
[org.clojure/clojurescript "1.9.946"]
[org.clojure/clojurescript "1.10.238"]
$INTERFACE_DEPS$]
:plugins [[lein-cljsbuild "1.1.4"]
[lein-figwheel "0.5.14"]]
Expand Down

0 comments on commit dac3e20

Please sign in to comment.