diff --git a/compiler/CompileContext.js b/compiler/CompileContext.js
index 1950d51f5..7309cbefa 100644
--- a/compiler/CompileContext.js
+++ b/compiler/CompileContext.js
@@ -510,9 +510,17 @@ class CompileContext extends EventEmitter {
var builder = this.builder;
varName = varName || removeExt(path.basename(relativePath)) + '_template';
- var requireResolveTemplate = requireResolve(builder, builder.literal(relativePath));
- var loadFunctionCall = builder.functionCall(this.helper('loadTemplate'), [ requireResolveTemplate ]);
- var templateVar = this.addStaticVar(varName, loadFunctionCall);
+ var templateVar;
+
+ if (this.options.browser) {
+ // When compiling a Marko template for the browser we just use `require('./template.marko')`
+ templateVar = this.addStaticVar(varName, builder.require(builder.literal(relativePath)));
+ } else {
+ // When compiling a Marko template for the server we just use `loadTemplate(require.resolve('./template.marko'))`
+ let loadTemplateArg = requireResolve(builder, builder.literal(relativePath));
+ let loadFunctionCall = builder.functionCall(this.helper('loadTemplate'), [ loadTemplateArg ]);
+ templateVar = this.addStaticVar(varName, loadFunctionCall);
+ }
this.pushMeta('tags', builder.literal(relativePath), true);
diff --git a/compiler/index.js b/compiler/index.js
index 585facf28..2f5407249 100644
--- a/compiler/index.js
+++ b/compiler/index.js
@@ -106,7 +106,7 @@ function compileForBrowser(src, filename, options, callback) {
options = null;
}
- options = extend({output: 'vdom'}, options);
+ options = extend({output: 'vdom', browser: true}, options);
return compile(src, filename, options, callback);
}
@@ -139,7 +139,7 @@ function compileFileForBrowser(filename, options, callback) {
options = null;
}
- options = extend({output: 'vdom'}, options);
+ options = extend({output: 'vdom', browser: true}, options);
return compileFile(filename, options, callback);
}
diff --git a/test/autotests/compiler-browser/include/expected.js b/test/autotests/compiler-browser/include/expected.js
new file mode 100644
index 000000000..afbc572cb
--- /dev/null
+++ b/test/autotests/compiler-browser/include/expected.js
@@ -0,0 +1,14 @@
+var marko_template = module.exports = require("marko/vdom").t(__filename),
+ include_target_template = require("./include-target.marko"),
+ marko_helpers = require("marko/runtime/vdom/helpers"),
+ marko_loadTag = marko_helpers.t,
+ include_tag = marko_loadTag(require("marko/taglibs/core/include-tag"));
+
+function render(data, out) {
+ include_tag({
+ _target: include_target_template,
+ foo: "bar"
+ }, out);
+}
+
+marko_template._ = render;
diff --git a/test/autotests/compiler-browser/include/include-target.marko b/test/autotests/compiler-browser/include/include-target.marko
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/autotests/compiler-browser/include/template.marko b/test/autotests/compiler-browser/include/template.marko
new file mode 100644
index 000000000..6a87e26eb
--- /dev/null
+++ b/test/autotests/compiler-browser/include/template.marko
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/autotests/compiler-browser/simple/expected.js b/test/autotests/compiler-browser/simple/expected.js
new file mode 100644
index 000000000..e743a8546
--- /dev/null
+++ b/test/autotests/compiler-browser/simple/expected.js
@@ -0,0 +1,44 @@
+var marko_template = module.exports = require("marko/vdom").t(__filename),
+ marko_helpers = require("marko/runtime/vdom/helpers"),
+ marko_forEach = marko_helpers.f,
+ marko_createElement = marko_helpers.e,
+ marko_const = marko_helpers.const,
+ marko_const_nextId = marko_const("6597f2"),
+ marko_node0 = marko_createElement("div", null, 1, marko_const_nextId())
+ .t("No colors!");
+
+function render(data, out) {
+ out.t("Hello ");
+
+ out.t(data.name);
+
+ out.t("! ");
+
+ if (data.colors.length) {
+ out.be("ul");
+
+ marko_forEach(data.colors, function(color) {
+ out.e("li", null, 1)
+ .t(color);
+ });
+
+ out.ee();
+ } else {
+ out.n(marko_node0);
+ }
+
+ if (data.colors.length) {
+ out.be("ul");
+
+ marko_forEach(data.colors, function(color) {
+ out.e("li", null, 1)
+ .t(color);
+ });
+
+ out.ee();
+ } else {
+ out.n(marko_node0);
+ }
+}
+
+marko_template._ = render;
diff --git a/test/autotests/compiler-browser/simple/template.marko b/test/autotests/compiler-browser/simple/template.marko
new file mode 100644
index 000000000..8c83d767c
--- /dev/null
+++ b/test/autotests/compiler-browser/simple/template.marko
@@ -0,0 +1,27 @@
+---
+Hello ${data.name}!
+
+
+
+ No colors!
+
+
+
+
+
+
+
+ No colors!
+
+
+---
\ No newline at end of file
diff --git a/test/compiler-browser-test.js b/test/compiler-browser-test.js
new file mode 100644
index 000000000..a4c4fd94b
--- /dev/null
+++ b/test/compiler-browser-test.js
@@ -0,0 +1,52 @@
+'use strict';
+require('./util/patch-module');
+
+var chai = require('chai');
+chai.config.includeStack = true;
+var path = require('path');
+var compiler = require('../compiler');
+var autotest = require('./autotest');
+var fs = require('fs');
+
+require('marko/node-require').install();
+
+describe('compiler (browser target)', function() {
+ var autoTestDir = path.join(__dirname, 'autotests/compiler-browser');
+
+ autotest.scanDir(autoTestDir, function run(dir, helpers, done) {
+ var templatePath = path.join(dir, 'template.marko');
+ var mainPath = path.join(dir, 'test.js');
+ var main;
+
+ if (fs.existsSync(mainPath)) {
+ main = require(mainPath);
+ }
+
+ if (main && main.checkError) {
+ var e;
+
+ try {
+ compiler.compileFileForBrowser(templatePath);
+ } catch(_e) {
+ e = _e;
+ }
+
+ if (!e) {
+ throw new Error('Error expected');
+ }
+
+ main.checkError(e);
+ done();
+
+ } else if (main && main.checkTemplate) {
+ var template = require('marko').load(templatePath, main.compilerOptions);
+ main.checkTemplate(template);
+ done();
+ } else {
+ var compiledSrc = compiler.compileFileForBrowser(templatePath, main && main.compilerOptions);
+ helpers.compare(compiledSrc, '.js');
+ done();
+ }
+ });
+
+});
\ No newline at end of file
diff --git a/widgets/browser.json b/widgets/browser.json
index 7a363aa01..3f0482ba4 100644
--- a/widgets/browser.json
+++ b/widgets/browser.json
@@ -6,5 +6,11 @@
"run": true,
"if": "!flags.contains('marko-widgets/no-client-init')"
}
+ ],
+ "requireRemap": [
+ {
+ "from": "./loadWidget.js",
+ "to": "./loadWidget-dynamic.js"
+ }
]
}
\ No newline at end of file
diff --git a/widgets/loadWidget-dynamic.js b/widgets/loadWidget-dynamic.js
new file mode 100644
index 000000000..7cc3e1325
--- /dev/null
+++ b/widgets/loadWidget-dynamic.js
@@ -0,0 +1,8 @@
+'use strict';
+
+module.exports = function load(typeName) {
+ // We make the assumption that the widget type name is a path to a
+ // fully resolved module path and that the module exists
+ // as a CommonJS module
+ return require(typeName);
+};
\ No newline at end of file
diff --git a/widgets/loadWidget.js b/widgets/loadWidget.js
new file mode 100644
index 000000000..ada1c0086
--- /dev/null
+++ b/widgets/loadWidget.js
@@ -0,0 +1,4 @@
+'use strict';
+module.exports = function load(typeName) {
+ throw new Error('Unable to load: ' + typeName);
+};
\ No newline at end of file
diff --git a/widgets/registry.js b/widgets/registry.js
index d69282f57..c449ad49a 100644
--- a/widgets/registry.js
+++ b/widgets/registry.js
@@ -1,3 +1,5 @@
+var loadWidget = require('./loadWidget');
+
var registered = {};
var loaded = {};
var widgetTypes = {};
@@ -27,7 +29,7 @@ function load(typeName) {
target = target();
}
if (!target) {
- target = require(typeName); // Assume the typeName has been fully resolved already
+ target = loadWidget(typeName); // Assume the typeName has been fully resolved already
}
loaded[typeName] = target || null;
}