Add external js in magento using requires-config.js - magento-2.0

I have created a custom module and added requires-config.js (app\code\Namespace\Modulename\view\frontend).
var config = {
map: {
'*': {
test: 'https://example.com/test.js'
}
}
};
After that I have deploy the static content, now I can see the external js has added in following location (pub\static_requirejs\frontend\Magento\luma\en_US),but still external js is not loaded in page source (using console).
Still I need to add the js files in layout?
<head>
<link src="https://example.com/test.js"/>
</head>

Its good practise to put your js in Modulename/view/frontend/web/js folder rather than loading from url.
var config = {
"map": {
"*": {
"test": "Modulename/js/test"
}
}
};
Also you don't need to add .js extenstion in the require js file.
then check it will load
Please clear the cache and also do static content deploy

Related

How to stop Webpack wrapping my JS in an IIFE so I can call my functions in .cshtml views

I've recently added WebPack 5 to my build process in my .NET Core MVC 7 application.
My goal is to be able to call my javascript functions from the javascript files WebPack generates inside my views.
I have a simple Index.cshtml file that includes a partial view and the generated javascript from webpack:
Index.cshtml
<div>
#await Html.PartialAsync("SettingsTab")
</div>
#section Scripts
{
<script defer src="~/dist/settings.entry.js"></script>
}
The SettingsTab constains a button that is trying to trigger a method from the settings.entry.js file:
SettingsTab.cshtml
<div>
<button type="button" onclick="saveProfileSettings()">Save Profile</button>
</div>
The settings.js file before webpack bundles it into the dist folder looks like this:
settings.js
import ('../css/settings.css')
function saveProfileSettings() {
// do stuff
}
When I wasn't using webpack I could directly call this function like I am trying to above.
However now when I reference the bundled js file it cannot call it.
Looking at the end of the settings.entry.js file it looks like webpack has bundled my code into an IIFE:
End of settings.entry.js
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be in strict mode.
(() => {
"use strict";
// omitted contents of settings.js
})();
/******/ })()
;
I would like to instruct WebPack not to wrap my code like this so I can directly call the functions elsewhere.
Now I did find out that I can use library in my webpack.config.js like so:
output: {
filename: "[name].entry.js",
path: path.resolve('wwwroot', 'dist'),
publicPath: "/dist/",
library: ['WebPack', '[name]']
},
With this I can successfully reference my functions using WebPack.settings.saveProfileSettings() but I do not want to do this. I want to be able to reference my functions directly as saveProfileSettings().
How can I change how WebPack packs my code so I can do this?

Custom js added in custom module in magento

I have created a module. In this a custom js file is added with requirejs-config.js, But to load the js file, I need to write the following lines on phtml,
<script type="text/javascript">
require(['jquery','customjs']});</script>
If I don't add the above line js is not adding .Can some body please tell is this the right approach or I am doing some thing wrong.
Require js code added at (Namespace\Modulename\view\frontend)
define([
'jquery',
'underscore',
'mage/template',
], function (
$,
_,
template
) {
//custom code
});
Yes this is the right approach. because you have created custom.js right . so that custom.js you need to call in your requirejs-config.js
But now when you want to use this actuall js functions and properties you need to pass below code
<script type="text/javascript">
require(['jquery','customjs']});</script>
What it mean actually , to load your customjs it requires jquery so first load the jquery then load your customjs and then you can pass the parameters.
require([ 'jquery', 'customjs'], function(){
alert("test");
});
so alert box will prompt when you add this in your template
Jfyi - in your requirejs-config.js you need to write like below code you dont'need to write extension of js file like.js as require js automatically render that . and lastly put the js file in web/js folder in your module
var config = {
"map": {
"*": {
"customjs": "Vendor_Modulename/js/custom"
}
}
};

Use wiredep to inject custom CSS

I need to inject custom CSS files everytime they are created after being compiled by gulp-less. So I tried to use wiredep with custom configurations, but without success.
I changed the tag from 'bower:css' to 'custom:css', specifically to my custom task. The bower:css for default wiredep injection is still there. But after run myinjection task nothing is injected even running the task without errors.
Another weird thing, when I run my task, the files injected by wiredep (the default) disappear.
What I'm missing?
Basicaly my files structure is like this:
|---app
|---styles
|---***
*.css
*.html
.custom.json
I'm not sure if I really need a file similar to bower.json, but I made may own custom.json
{
"name": "custom",
"version": "0.0.1",
"main": [
"app/styles/**/*.css",
"app/scripts/**/*.js //pretend to inject custom js later
]
}
The task in gulpfile.js is like this:
gulp.task('myinject', function () {
var myinject = require('wiredep').stream;
var combined = Combine (
gulp.src('app/*.html'),
myinject({
directory: 'app',
bowerJson: require('./custom.json'),
dependencies: false,
html:
{
block: /(([ \t]*)<!--\s*custom:*(\S*)\s*-->)(\n|\r|.)*?(<!--\s*endcustom\s*-->)/gi,
detect: {
js: /<script.*src=['"](.+)['"]>/gi,
css: /<link.*href=['"](.+)['"]/gi
},
replace: {
js: '<script src="{{filePath}}"></script>',
css: '<link rel="stylesheet" href="{{filePath}}" />'
}
}
}),
gulp.dest('app')
);
combined.on('error', function(err) {
console.warn(err.message);
});
return combined;
});
Thanks in advance
I had a similar issue that I resolved with gulp-inject rather than wiredep.
Wiredep works fine with me when I need to include a third-party dependency (e.g. a bower package with a valid main file declared in the bower.json or a file with the same name as the directory).
However, when you want to include only a specific file (e.g. only the main.css of html5-boilerplate) gulp-inject is much simpler. Here is an extract of the doc :
gulp.task('index', function () {
var target = gulp.src('./src/index.html');
var sources = gulp.src(['./src/**/*.js', './src/**/*.css'], {read: false});
return target.pipe(inject(sources))
.pipe(gulp.dest('./src'));
});

Serving an "index.html" file in public/ when using MeteorJS and Iron Router?

I want to serve a static HTML file from MeteorJS's public folder (as is possible with Rails and Express). The reason I'm doing this is because I have one template for the dynamic "admin" part of my webapp and another for the sales-y "frontend" part of the app.
I don't want this file to be wrapped in a Meteor template as suggested in this answer as it will automatically bring in the minified CSS, etc... that the dynamic pages use.
Is there a way I can setup the public folder (and all its subfolders) so that it serves index.html? This way http://app.com/ will load public/index.html?
You could use the private folder instead and then use Assets.getText to load the contents of the file, then serve it with a server-side router from iron-router.
So off the top of my head the code would look something like this:
if (Meteor.isServer) {
Router.map(function() {
this.route('serverRoute', {
path: '/',
where: 'server',
action: function() {
var contents = Assets.getText('index.html');
this.response.end(contents);
}
});
});
}
this is what I put in bootstrap.js
Router.route('/', {
where: 'server'
}).get(function() {
var contents;
contents = Assets.getText('index.html');
return this.response.end(contents);
});

Excluding bootstrap from specific routes in Meteor

I was hoping anyone could give some input on this,
I'm creating a meteor app in which I would like to use bootstrap to creating the admin environment, but have the visitor facing side using custom css. When I add the bootstrap package to my app using meteor it's available on every page, is there a way to restrict the loading of bootstrap to routes that are in '/admin' ?
When you add bootstrap package it's not possible. You can, however, add bootstrap csses to public directory and then load them in a header subtemplate that will only be rendered when you're in the dashboard.
EDIT
But then how would you go about creating seperate head templates?
Easy:
<head>
...
{{> adminHeader}}
...
</head>
<template name="adminHeader">
{{#if adminPage}}
... // Put links to bootstrap here
{{/if}}
</template>
Template.adminHeader.adminPage = function() {
return Session.get('adminPage');
}
Meteor.router.add({
'/admin': function() {
Session.set('adminPage', true);
...
}
});
DISCLAIMER: I am unsure of a 'meteor way' to do this, so here is how I would do it with plain JS.
jQuery
$("link[href='bootstrap.css']").remove();
JS - Credit to javascriptkit
function removejscssfile(filename, filetype){
var targetelement=(filetype=="js")? "script" : (filetype=="css")? "link" : "none" //determine element type to create nodelist from
var targetattr=(filetype=="js")? "src" : (filetype=="css")? "href" : "none" //determine corresponding attribute to test for
var allsuspects=document.getElementsByTagName(targetelement)
for (var i=allsuspects.length; i>=0; i--){ //search backwards within nodelist for matching elements to remove
if (allsuspects[i] && allsuspects[i].getAttribute(targetattr)!=null && allsuspects[i].getAttribute(targetattr).indexOf(filename)!=-1)
allsuspects[i].parentNode.removeChild(allsuspects[i]) //remove element by calling parentNode.removeChild()
}
}
removejscssfile("bootstrap.css", "css")
However, doing that would complete remove it from the page. I am not sure whether meteor would then try to readd it when a user goes to another page. If that does not automatically get readded, then you have an issue of bootstrap not being included when someone goes from the admin section to the main site, which would break the look of the site.
The way I would get around that would be to disable and enable the stylesheets:
Meteor.autorun(function(){
if(Session.get('nobootstrap')){
$("link[href='bootstrap.css']").disabled = true;
}else{
$("link[href='bootstrap.css']").disabled = false;
}
});
There my be other bootstrap resources which may need to be removed, take a look at what your page is loading.
To use jQuery in the same way but for the javascript files, remember to change link to script and href to src
From my tests, Meteor does not automatically re-add the files once they have been removed so you would need to find some way of re-adding them dynamically if you want the same user to be able to go back and forth between the main site and the admin site. Or simply if the http referrer to the main site is from the admin, force reload the page and then the bootstrap resources will load and everything will look pretty.
P.s. make sure you get the href correct for the jQuery version
If somebody is interested in including any js/css files, I've written a helper for it:
if (Meteor.isClient) {
// dynamic js / css include helper from public folder
Handlebars.registerHelper("INCLUDE_FILES", function(files) {
if (files != undefined) {
var array = files.split(',');
array.forEach(function(entity){
var regex = /(?:\.([^.]+))?$/;
var extension = regex.exec(entity)[1];
if(extension == "js"){
$('head').append('<script src="' + entity + '" data-dynamicJsCss type="text/javascript" ></script>');
} else if (extension == "css"){
$('head').append('<link href="' + entity + '" data-dynamicJsCss type="text/css" rel="stylesheet" />');
};
});
}
});
Router.onStop(function(){
$("[data-dynamicJsCss]").remove();
});
}
Then simply use:
{{INCLUDE_FILES '/css/html5reset.css, /js/test.js'}}
in any of your loaded templates :)

Resources