Skip to content

Commit 27df77f

Browse files
committed
Add ability to provide React version rather than always loading the built-in version. Closes #113
1 parent 3ae436a commit 27df77f

File tree

5 files changed

+98
-6
lines changed

5 files changed

+98
-6
lines changed

src/React.Core/IReactSiteConfiguration.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,5 +130,17 @@ public interface IReactSiteConfiguration
130130
/// </summary>
131131
/// <returns></returns>
132132
IReactSiteConfiguration SetAllowMsieEngine(bool allowMsieEngine);
133+
134+
/// <summary>
135+
/// Gets or sets whether the built-in version of React is loaded. If <c>false</c>, you must
136+
/// provide your own version of React.
137+
/// </summary>
138+
bool LoadReact { get; set; }
139+
/// <summary>
140+
/// Sets whether the built-in version of React is loaded. If <c>false</c>, you must
141+
/// provide your own version of React.
142+
/// </summary>
143+
/// <returns>The configuration, for chaining</returns>
144+
IReactSiteConfiguration SetLoadReact(bool loadReact);
133145
}
134146
}

src/React.Core/JavaScriptEngineFactory.cs

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,29 @@ protected virtual void InitialiseEngine(IJsEngine engine)
135135
{
136136
var thisAssembly = typeof(ReactEnvironment).Assembly;
137137
engine.ExecuteResource("React.Resources.shims.js", thisAssembly);
138-
engine.ExecuteResource("React.Resources.react-with-addons.js", thisAssembly);
139-
engine.Execute("var React = global.React");
140-
engine.ExecuteResource("React.Resources.JSXTransformer.js", thisAssembly);
138+
if (_config.LoadReact)
139+
{
140+
engine.ExecuteResource("React.Resources.react-with-addons.js", thisAssembly);
141+
engine.Execute("React = global.React");
142+
engine.ExecuteResource("React.Resources.JSXTransformer.js", thisAssembly);
143+
}
141144

142-
// Only scripts that don't need JSX transformation can run immediately here
143-
// JSX files are loaded in ReactEnvironment.
145+
LoadUserScripts(engine);
146+
if (!_config.LoadReact)
147+
{
148+
// We expect to user to have loaded their own versino of React in the scripts that
149+
// were loaded above, let's ensure that's the case.
150+
EnsureReactLoaded(engine);
151+
}
152+
}
153+
154+
/// <summary>
155+
/// Loads any user-provided scripts. Only scripts that don't need JSX transformation can
156+
/// run immediately here. JSX files are loaded in ReactEnvironment.
157+
/// </summary>
158+
/// <param name="engine">Engine to load scripts into</param>
159+
private void LoadUserScripts(IJsEngine engine)
160+
{
144161
foreach (var file in _config.ScriptsWithoutTransform)
145162
{
146163
try
@@ -161,6 +178,23 @@ protected virtual void InitialiseEngine(IJsEngine engine)
161178
}
162179
}
163180

181+
/// <summary>
182+
/// Ensures that React has been correctly loaded into the specified engine.
183+
/// </summary>
184+
/// <param name="engine">Engine to check</param>
185+
private static void EnsureReactLoaded(IJsEngine engine)
186+
{
187+
var result = engine.CallFunction<bool>("ReactNET_initReact");
188+
if (!result)
189+
{
190+
throw new ReactNotInitialisedException(
191+
"React has not been loaded correctly. Please expose your version of React as a global " +
192+
"variable named 'React', or enable the 'LoadReact' configuration option to " +
193+
"use the built-in version of React."
194+
);
195+
}
196+
}
197+
164198
/// <summary>
165199
/// Gets the JavaScript engine for the current thread. It is recommended to use
166200
/// <see cref="GetEngine"/> instead, which will pool/reuse engines.

src/React.Core/ReactSiteConfiguration.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public ReactSiteConfiguration()
3636
UseHarmony = true;
3737
ReuseJavaScriptEngines = true;
3838
AllowMsieEngine = true;
39+
LoadReact = true;
3940
}
4041

4142
/// <summary>
@@ -203,5 +204,22 @@ public IReactSiteConfiguration SetAllowMsieEngine(bool allowMsieEngine)
203204
AllowMsieEngine = allowMsieEngine;
204205
return this;
205206
}
207+
208+
/// <summary>
209+
/// Gets or sets whether the built-in version of React is loaded. If <c>false</c>, you must
210+
/// provide your own version of React.
211+
/// </summary>
212+
public bool LoadReact { get; set; }
213+
214+
/// <summary>
215+
/// Sets whether the built-in version of React is loaded. If <c>false</c>, you must
216+
/// provide your own version of React.
217+
/// </summary>
218+
/// <returns>The configuration, for chaining</returns>
219+
public IReactSiteConfiguration SetLoadReact(bool loadReact)
220+
{
221+
LoadReact = loadReact;
222+
return this;
223+
}
206224
}
207225
}

src/React.Core/Resources/shims.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*/
99

1010
var global = global || {};
11+
var React;
1112

1213
// Basic console shim. Caches all calls to console methods.
1314
function MockConsole() {
@@ -40,6 +41,29 @@ if (!Object.freeze) {
4041
Object.freeze = function() { };
4142
}
4243

44+
/**
45+
* Finds a user-supplied version of React and ensures it's exposed globally.
46+
*
47+
* @return {bool}
48+
*/
49+
function ReactNET_initReact() {
50+
if (typeof React !== 'undefined') {
51+
// React is already a global, woohoo
52+
return true;
53+
}
54+
if (global.React) {
55+
React = global.React;
56+
return true;
57+
}
58+
if (typeof require === 'function') {
59+
// CommonJS-like environment (eg. Browserify)
60+
React = require('react');
61+
return true;
62+
}
63+
// :'(
64+
return false;
65+
}
66+
4367
function ReactNET_transform(input, harmony, stripTypes) {
4468
try {
4569
return global.JSXTransformer.transform(input, {

src/React.Sample.Webpack/webpack.config.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ module.exports = {
2222
module: {
2323
loaders: [
2424
// Transform JSX in .jsx files
25-
{ test: /\.jsx$/, loader: 'jsx-loader?harmony' }
25+
{ test: /\.jsx$/, loader: 'jsx-loader?harmony' },
26+
// Uncomment this if you want to use your own version of React instead of the version
27+
// bundled with ReactJS.NET.
28+
//{ test: require.resolve('react'), loader: 'expose?React' }
2629
],
2730
},
2831
resolve: {
@@ -31,6 +34,7 @@ module.exports = {
3134
},
3235
externals: {
3336
// Use external version of React (from CDN for client-side, or bundled with ReactJS.NET for server-side)
37+
// Comment this out if you want to load your own version of React
3438
react: 'React'
3539
}
3640
};

0 commit comments

Comments
 (0)