I'm accessing API's hosted by AWS API Gateway with Vue.Js.
There's some pretty good instructions here http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-generate-sdk-javascript.html.
I have a bunch of different components, each of which will get data from a different API GET call. Initially I tried adding all the script files to my index.html and doing the following:
RetailerDetails.vue:
<script>
export default {
name: 'RetailerDetails',
mounted() {
var apigClient = apigClientFactory.newClient({
accessKey: 'blah',
secretKey: 'blah',
});
apigClient.businessGet = function (params, body, additionalParams) {
if (additionalParams === undefined) { additionalParams = {}; }
apiGateway.core.utils.assertParametersDefined(params, [], ['body']);
var businessGetRequest = {
verb: 'get'.toUpperCase(),
path: pathComponent + uritemplate('/business').expand(apiGateway.core.utils.parseParametersToObject(params, [])),
headers: apiGateway.core.utils.parseParametersToObject(params, []),
queryParams: apiGateway.core.utils.parseParametersToObject(params, []),
body: body
};
return apiGatewayClient.makeRequest(businessGetRequest, authType, additionalParams, config.apiKey);
};
},
}
That didn't work, I got ReferenceError: apigClientFactory is not defined.
So then I tried taking the script tags out of my index.html and adding the following lines to my component:
require('../assets/js/lib/axios/dist/axios.standalone.js');
require('../assets/js/lib/CryptoJS/rollups/hmac-sha256.js');
require('../assets/js/lib/CryptoJS/rollups/sha256.js');
require('../assets/js/lib/CryptoJS/components/hmac.js');
require('../assets/js/lib/CryptoJS/components/enc-base64.js');
require('../assets/js/lib/url-template/url-template.js');
require('../assets/js/lib/apiGatewayCore/sigV4Client.js');
require('../assets/js/lib/apiGatewayCore/apiGatewayClient.js');
require('../assets/js/lib/apiGatewayCore/simpleHttpClient.js');
require('../assets/js/lib/apiGatewayCore/utils.js');
require('../assets/js/custom/apigClient.js');
This don't work either, now I get ReferenceError: Can't find variable: CryptoJS
which from what I understand is because I haven't referenced the flles properly?
What do I need to do?
Don't put javascript files in the assets folder. Put them in the static folder instead. If you are using the CLI install, Webpack sorts through the assets and takes care of things like image and fonts, but not javascript files.
When I put the files in the /static/ or something like /static/js/ and then bring them in with:
<script type="text/javascript" src="/static/apigClient.js"></script>
the functions are available to my Vue components. Maybe there's a nicer way that doesn't pollute the global namespace, but this is a pretty easy solution (assuming it also works for you).
Related
I've installed several libraries using NPM.
You have to load the file to use it there.All installed libraries are under the node_modules
The designation is like this.
<script src="../node_modules/vue/dist/vue.js"></script>
I'm sure it's on the server, I'm sure the URL of the script tag is correct
And I get the following error in the script, even though it is specified like this
login.html:45 GET https://***/node_modules/vue/dist/vue.js net::ERR_ABORTED 404
The JS file I prepared separately is loaded, but the original vue.js is not, so an error is coming back.
That's what we're trying to do with VUE.
I'm going to use Ajax to create an SPA
/* eslint-disable no-console */
const vue = require("vue"); //I added it, but it's still not working.
const axios = require("axios"); //I added it, but it's still not working.
var app = new Vue({
el: "#app",
data: {
url: "https://*****",
user: "",
password: "",
res: ""
},
methods: {
login: function () {
axios.post(this.url, {
user: this.user,
password: this.password
})
.then(function (response) {
this.res = response.data.d;
if (this.res === true) {
//true
} else {
//failed
}
})
.catch(function (error) {
alert('System error');
});
}
}
})
This is how usually use it from node_module
import Vue from 'vue'; // this will check inside node_modules for the file and include
Instead of loading the files through a script tag, use require() in your javascript. For example:
const express = require("express");
const vue = require("vue");
This will work on both the client and on the server.
Why not use a CDN?
This way, the browser will not have to download the Vue file from your server if it has already been cached. Also, you may be able to use the vue.min.js file which will load even faster than the normal Vue dist file...
For example, here is a script from cdnjs.com you could try:
<script
src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"
integrity="sha256-ngFW3UnAN0Tnm76mDuu7uUtYEcG3G5H1+zioJw3t+68="
crossorigin="anonymous"></script>
Try replacing your script tag with this.
We use environment variables within our angular app to read settings etc but is there a way to generate assets/files on build?
Basically we'd like to create an 'auth/settings.js' file in the assets folder containing client id's and apiUrl's unique to each environment. These will be used in the index.html (so outside of the angular app bootstrap )
e.g. the values in the environment.ts exported into a js / json file output to the assets folder so they can be read in index.html
export const environment = {
production: false,
title: 'default',
clientId: 'xxxx-xxxx-xxxx-xxxx-xxxx',
clientUrl: 'https://localhost:4200/app',
apiUrl: 'https://localhost/api'
};
I have read that you can use mulitapps:
https://github.com/angular/angular-cli/wiki/stories-multiple-apps
This may work but looks like a lot of copy and pasting and we'll have quite a few versions of the build - I'm not sure if you can declare the common settings once and just extend the extra app settings (inheritance)?
Thanks
What we are doing in our case is actually having an config.json and config.[env-name].json files in app/config folder that configured in project assets. The config.json file is getting fetched before angular bootstrap using browser Fetch API
On our build server we are just replacing the content of config.json withconfig.staging.json or config.prod.json based on environment build. Also we have AppSettings class that gets created on bootstrap. Here is how it is looks like:
fetch(configUrl, { method: 'get' })
.then((response) => {
response.json()
.then((data: any) => {
if (environment.production) {
enableProdMode();
};
platformBrowserDynamic([{ provide: AppSettings, useValue: new AppSettings(data.config) }]).bootstrapModule(AppModule);
});
});
UPDATE:
If you need to stick some values based on your env in to index.html you might need to consider doing that on your build server. You can rather string replace the values or you can have index.[env-name].thml files so you just overwrite the index.html based on environment build.
Also check out this issues
- https://github.com/angular/angular-cli/issues/7506
- https://github.com/angular/angular-cli/issues/3855
While working on a Web app using Webpack to manage JavaScript dependencies, I stumbled upon the problem i'm going to describe.
Loading dependencies passing strings to require() works beautifully:
// main.js
var jQuery = require('jquery');
Here, jquery is installed with Bower, and Webpack is correctly configured to automatically resolve Bower modules.
Now, I'm working on the problem of conditionally loading modules, with particular regard to the situation where modules have to be downloaded from a CDN, or from the local server if the CDN fails. I use scriptjs to asynchronously load from the CDN, by the way. The code I'm writing is something like this:
var jQuery = undefined;
try {
jQuery = require('jquery-cdn');
} catch (e) {
console.log('Unable to load jQuery from CDN. Loading local version...');
require('script!jquery');
jQuery = window.jQuery;
}
// jQuery available here
and this code works beautifully as well.
Now, since I obviously have a lot of dependencies (Handlebars, Ember, etc.) that I want to try to load from a CDN first, this code starts to get a little redundant, so the most logical thing I try to do is to refactor it out into a function:
function loadModule(module, object) {
var lib = undefined;
try {
lib = require(module + '-cdn');
} catch (e) {
console.log('Cannot load ' + object + ' from CDN. Loading local version...');
require('script!' + module);
lib = window[object];
}
return lib;
}
var jQuery = loadModule('jquery', 'jQuery');
var Handlebars = loadModule('handlebars', 'Handlebars');
// etc...
The problem is that Webpack has a particular behaviour when dealing with expressions inside require statements, that hinders my attempts to load modules in the way described above. In particular, when using an expression inside require it
tries to include all files that are possible with your expression
The net effect is a huge pile of error messages when I try to run Webpack with the above code.
Though the linked resources suggest to explicitly declare the path of the JavaScript files to include, what I fail to get is how to do the same thing when I cannot, or don't want to, pass a precise path to require, but rather use the automatically resolved modules, as shown.
Thanks all
EDIT:
I still don't known how to use expressions to load those scripts, however, I designed a workaround. Basically, the idea is to explicitly write the require('script') inside a callback function, and then dinamically call that function when it's time. More precisely, I prepared a configuration file like this:
// config.js
'use strict';
module.exports = {
'lib': {
'jquery': {
'object': 'jQuery',
'dev': function() { require('script!jquery'); },
'dist': function() { return require('jquery-cdn'); },
'cdn': '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js'
},
'handlebars': {
// ...
}
}
};
Inside my main code I, then, define an array of resources to load, like:
var config = require('./config.js');
var resources = [ config.lib.jquery, config.lib.handlebars, ... ];
And then when I have to load the development version, or the distribution version, I dinamically call:
// Inside some kind of cycle
// resource = resources[index]
try {
window[resource.object] = resource.dist();
} catch (e) {
console.log('Cannot load ' + resource.object + ' from CDN. Loading local version...');
resource.dev();
}
Here there's a more complete example of this in action.
I have some const values, which are used throughout the application as well as by jade for static code generation.
I was defining the data in file (const.js) as below.
my.const = (function () {
return {};
}());
my.const.testType = Object.freeze({
main: {key: 1, value: "Main"}
});
I include this file with script tag, and the variables are accessible to my application.
But, I do not find a way to read this file, and access the data object, my.const in jade. For that, I have to create a json file and configure grunt as
jade: {
dist: {
options: {
pretty: true,
data: function(dest, src) {
console.log(dest, src);
return grunt.file.readJSON('app/const.json');
}
},
files: [...
I use grunt-contrib-jade plugin.
I cannot use const.js as it needs to be a valid json file (api). So, I have to keep and maintain 2 files (js and json) with same data. How can I either
read the js file (const.js) with grunt and access the data (my.const) OR
include the data from json file, statically so that scripts below can acccess the data. Simply including json file gives error (Uncaught SyntaxError: Unexpected token :)
or is there a better way (any grunt plugin to generate the js file, ...). I cannot think any.
Thanks.
Assuming you are using node js, in your const.js file, add at the bottom:
.
.
if(module && module.exports) {
module.exports = m;
}
At the top of your grunt file, require the const.js file:
var m = require('../path/to/const.js');
And then, in your grunt configuration data function:
data: function(dest, src) {
console.log(dest, src);
return m;
}
I have an application using node.js backend and require.js/backbone frontend.
My backend has a config/settings system, which depending on the environment (dev, production, beta) can do different things. I would like to propagate some of the variables to the client as well, and have them affect some template rendering (e.x change the Title or the URL of the pages).
What is the best way to achieve that?
I came up with a way to do it, and it seems to be working but I don't think its the smartest thing to do and I can't figure out how to make it work with requirejs optimizer anyway.
What I do is on the backend I expose an /api/config method (through GET) and on the client
I have the following module config.js:
// This module loads an environment config
// from the server through an API
define(function(require) {
var cfg = require('text!/api/config');
return $.parseJSON(cfg);
});
any page/module that needs config will just do:
var cfg = require('config');
As I said I am having problem with this approach, I can't compile/optimize my client code
with requirejs optimizer since /api/config file doesn't exist in offline during optimization. And I am sure there are many other reason my approach is a bad idea.
If you use use module bundlers such as webpack to bundle JavaScript files for usage in a browser, you can reuse your Node.js module for the client running in a browser. In other words, put your settings or configuration in Node.js modules, and share them between the backend and the client.
For example, you have the following settings in config.js:
Normal Node.js module: config.js
const MY_THIRD_PARTY_URL = 'https://a.third.party.url'
module.exports = { MY_THIRD_PARTY_URL }
Use the module in Node.js backend
const config = require('path-to-config.js')
console.log('My third party URL: ', config.MY_THIRD_PARTY_URL)
Share it in the client
import config from 'path-to-config.js'
console.log('My third party URL: ', config.MY_THIRD_PARTY_URL)
I do the following (note that this is Jade, i have never used require.js or backbone, however as long as you can pass variables from express into your templating language, you should be able to place JSON in data-* attributes on any element you want.)
// app.js
app.get('/', function(req, res){
var bar = {
a: "b",
c: Math.floor(Math.random()*5),
};
res.locals.foo = JSON.stringify(bar);
res.render('some-jade-template');
});
// some-jade-template.jade
!!!
html
head
script(type="text/javascript"
, src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js")
script(type="text/javascript")
$.ready(init);
function init(){
var json = $('body').attr('data-stackoverflowquestion');
var obj = JSON.parse(json);
console.log(obj);
};
body(data-stackoverflowquestion=locals.foo)
h4 Passing data with data-* attributes example