I'm using backbone with requireJS and I have several template files, I would like to use require() to load the templates without passing it in the module definition, for instance inside a login function in the view, I'd want to do somethign like
var html = require( ['text!templates/users/login_form.html'] );
Did you download the RequireJS text plugin? You need to download it and it put it your project before RequireJS can use text resources as dependencies. You can read about it here on the project page and also in their API documentation.
Yes you can!
loginTemplate = require(['text!templates/users/login_form.html'],
function(Template) {
return Template;
});
this should help you :-)
You can do that asking for "require" as a dependency in the module definition
define(["require", "other_dependencies"], function(require, etc) {
var template = require('text!templates/users/login_form.html');
});
Related
How to include an entire file into my bundle main.js?
ES6 can import/export functions and classes. But what if i want to include the whole content from another file into my bundle main.js? how to do it?
I came across the query on Stackoverflow: Managing jQuery plugin dependency in webpack.
I'm not sure about this question though. Those options given there seem to target injecting implicit globals, configuring this, disabling AMD, to include large dists. I don't think this is what i want.
Let's say i have two files in src directory
1- rough.js
const rgh = "qwerty"
2- index.js
import './rough.js' //something like this
console.log (rgh)
Now what i expect in bundle.js is
const rgh = "query";
console.log(rgh)
I just want all the content inside one of my file to get all transported to index.js for webpack to bundle them
Those options given there seem to target injecting implicit globals,
configuring this, disabling AMD, to include large dists. I don't think
this is what i want.
To understand this you need to understand what webpack is doing for you. Web pack takes a series of Javascript files (and more importantly their contents) and parses these into one file. That's what it does from a file point of view, but if you ignore the file and think about what it does from a code point of view, it takes each one of the imported objects and makes them available to other objects depending upon the rules you define in your code (using import and export). You can think of this from a closure point of view something like this:
if you have some code like:
import a from 'a.js';
export default b(){
console.log(a.test());
}
This will be turned into something like, in one js file:
var a = (function() {
var testStr = "test";
function test(){
return testStr;
}
return {test:test};
})();
var b = (function(a) {
console.log(a.test());
})(a);
So you can see that the file isn't really important. What's important is the scope. b can use a because it is injected into it's scope (In this instance as a IIFE).
In the above example a and b are in the global scope but testStr isn't.
So when your talking about "importing my file", you need to forget about that and think about what objects in that file you want to import how. Any variables "in that file" declared directly var a = ....; are in the global scope. So it sounds like what you want to do is import the objects in that file into the global scope.
you just need to import that file in main.js
like this way
I'm trying to add dynamic import into my code to have a better performance on the client-side. So I have a webpack config where is bundling js files. On SFCC the bundled files are in the static folder where the path to that files is something like this: /en/v1569517927607/js/app.js)
I have a function where I'm using dynamic import of es6 to call a module when the user clicks on a button. The problem is that when we call for that module, the browser doesn't find it because the path is wrong.
/en/lazyLoad.js net::ERR_ABORTED 404 (Not Found)
This is normal because the file is on /en/v1569517927607/js/lazyLoad.js.
There is a way to get it from the right path? Here is my code.
window.onload = () => {
const lazyAlertBtn = document.querySelector("#lazyLoad");
lazyAlertBtn.addEventListener("click", () => {
import(/* webpackChunkName: "lazyLoad" */ '../modules/lazyLoad').then(module => {
module.lazyLoad();
});
});
};
I had the same problem and solved it using the Merchant Tools > SEO > Dynamic Mapping module in Business Manager.
There you can use a rule like the following to redirect the request to the static folder:
**/*.bundle.js i s,,,,,/js/{0}.bundle.js
All my chunk files are named with the <module>.bundle pattern.
Here you can find more info :
https://documentation.b2c.commercecloud.salesforce.com/DOC1/topic/com.demandware.dochelp/content/b2c_commerce/topics/search_engine_optimization/b2c_dynamic_mappings.html
Hope this helps.
I believe you'll likely need to do some path.resolve() magic in either your import statement or your webpack.config.js file as is shown in the accepted answer to this question: Set correct path to lazy-load component using Webpack - ES6
We did it in a different way. That required two steps
From within the template file add a script tag that creates a global variable for the static path. Something like
// inside .isml template
<script>
// help webpack know about the path of js scripts -> used for lazy loading
window.__staticPath__ = "${URLUtils.httpsStatic('/')}";
</script>
Then you need to instruct webpack to know where to find chunks by changing __webpack_public_path__ at runtime
// somewhere in your main .js file
// eslint-disable-next-line
__webpack_public_path__ = window.__staticPath__ + 'js/';
Optional step:
You might also want to remove code version from your __staticPath__ using replace (at least we had to do that)
__webpack_public_path__ = window.__staticPath__.replace('{YOUR_CODE_VERSION_GOES_HERE}', '') + 'js/';
I'm using Laravel 5 Boilerplate that comes with some structure already done.
I want to call a simple JavaScript method from the blade. Here's what I did:
1) Created file called test123.js
content of test123.js:
function test123() {
$(document).ready(function () {
console.log('hello from test123');
});
}
2) I opened the existing app.js and added:
import './test123';
3) I called npm dev run - all green, all OK.
4) In blade index.blade.php I typed:
#push('after-scripts')
<script>
test123();
</script>
#endpush
I went to compiled file:
<script src="http://foo.local/js/backend.js?id=8dbe74e012c3122422da"></script>
My method is there:
however it's not visible.
I guess it's about scopes? I don't want to make it window.test123. Should I? I just want define good old JS / jQuery method and invoke it only when needed in specific templates.
"Modern" JS is not my strong point as I find it very convoluted. I haven't touched default webpack.mix.js.
mix.setPublicPath('public');
mix.sass('resources/sass/frontend/app.scss', 'css/frontend.css')
.sass('resources/sass/backend/app.scss', 'css/backend.css')
.js('resources/js/frontend/app.js', 'js/frontend.js')
.js([
'resources/js/backend/before.js',
'resources/js/backend/app.js',
'resources/js/backend/after.js'
], 'js/backend.js')
.extract([
'jquery',
'bootstrap',
'popper.js/dist/umd/popper',
'axios',
'sweetalert2',
'lodash',
'#fortawesome/fontawesome-svg-core',
'#fortawesome/free-brands-svg-icons',
'#fortawesome/free-regular-svg-icons',
'#fortawesome/free-solid-svg-icons'
]);
Please help me to achieve this simple thing. I know the solution probably is not difficult but I don't know what to do…
Thank you.
Edit 1: I almost forgot. Here's the Boilerplate structure:
Edit 2: User brk requested some more screenshots:
Try exporting the function explicitly:
export function test123() {...}
and later import it:
import 'test123' from './test123';
You can try do this with require.js
//declare fn test123
test123(){ ...do something}
module.exports.test123 = test123;
and then
let test123 = require('./test123');
Here you can find more information about using require.js in browser with jquery https://requirejs.org/docs/jquery.html
I'm building a new application using Marionette and RequireJS, and I've got the following structure:
/main.js -- Main require() call that includes app.js and calls Application.start()
/app.js -- Application definition
/modules
/sub
/controller.js -- Defines a sub-application, requires app.js
...
I'm trying to keep dependencies at the top level of each file, as opposed to using require() inline, so that the r.js compiler can find them. The problem is, in my controller.js file, I am requiring app.js (in order to add initializers) and so I cannot require controller.js in app.js until after the Application has initialized, which means I can't put controller in the top-level define() array.
A simplified example of the currently working code:
// app.js
define(['marionette'], function(Marionette) {
var Application = new Marionette.Application();
Application.on("initialize:after", function() {
require(['modules/sub/controller'], function() {
Backbone.history.start();
});
});
});
// controller.js
define(['app'], function(Application) {
Application.module('SubApplication', function(SubApplication, Application, Backbone, Marionette, $, _) {
var router = Marionette.AppRouter.extend({
appRoutes: { "foo": "bar" }
});
var controller = { foo: function() {} };
Application.addInitializer(function() {
new router({ controller: controller });
});
});
});
I'm still fairly new to both Require and Marionette, so any suggestions would be welcome! I do know that I can include the files I want via the include option to r.js, but I thought this question was worth asking nonetheless.
The way I've chosen to do it in my book on Marionette and RequireJS is to require inline the modules that are only necessary for a subset of functionality. This simplifies development, and also means that modules won't be loaded unless that code path is triggered.
R.js will find inline dependencies just fine (provided they're defined as strings, i.e. not computed dynamically). In addition, they will also work with Almond.js (but don't forget to use the findNestedDependencies option in your build file).
Hope this helps!
I am learning backbone js, trying to make a small project.
In the of te page, I load require.js and text.js from the cloudflare CDN
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.8/require.min.js">//</script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/require-text/2.0.10/text.js">//</script>
I have made a backbone view called "Boxes":
var Boxes = Backbone.View.extend({
// Choose an element.
el : '.content',
render : function () {
// Captur "this" -> the backbone view itself.
var that = this;
$(this.el).html('how do I load a html template here?');
}
});
Problems:
When I add the text.js plugin to the page, I get the following error:
Mismatched anonymous define() module: function (module) { 'use strict'; ......
So I can't have the require.js and the text.js both loaded, it gives me the above error even on a blank page without any other scripts on it.
After I make the require js work with text js, how do I load an html template for that view?
Right now I know how to do it when I write my templates inline, in the index.html page.
I do it like this:
var Boxes = Backbone.View.extend({
el : '.content',
render : function () {
var that = this; // This backbone view
var template = _.template($('#user-list-template').html(), {});
that.$el.html(template);
}
});
Thank you!
In your HTML file, you only need to load requrejs like as shown in this index.html
<script type="text/javascript" data-main="js/main" src="js/libs/require-2.1.2.min.js"></script>
In above, "data-main" tells requirejs where to load its bootstrap file and in this case, it is under "js/main.js"
You can find the file in here.
In the main.js file, you will need to specify
require.config({ ... });
to configure requirejs.
After that you can use "define()/require()" to load the templates like...
define(['text!../../templates/app/content.about.html'],...);
See here for a complete example.
When you use require.js, you only use one script tag in your page. Everything else is loaded by Require.js.
To use a plugin, you'll configure it in a require.config
require.config({
paths: {
text: "path/to/text"
}
});
Then in your modules, you simply call it:
define([
"text!path/to/tpl"
], function( tplString ) {
});
Note though, that if you're managing templates, the best would be to load the template pre-compiled. Text plugin only return a string, this is not very good for optimisation and force you to repeat the template compilation logic. You should use a template loader plugin, for underscore/lodash micro-template, I recommend you this one: https://github.com/tbranyen/lodash-template-loader
If you want an example of an app using Require.js and Backbone, you should really check Backbone-Boilerplate: https://github.com/backbone-boilerplate/backbone-boilerplate
Backbone-Boilerplate is good way to setup your project fast using the best practices around Backbone development. Plus it use AMD extensively, so you'll have a working setting if it is your first time around.