I have a bootstrap template with custom css and js that I want to use with ember.js.
I am stuck with integrating the js.
I have to say that I usually don't work on the frontend side, so if this is an obvious mistake I made, excuse me.
I want to stick with the js I have from the template and don't want to include ember-bootstrap for example.
node version: v14.15.5, ember-cli: 3.25.0
npm packages to include: bootstrap#5.0.0-beta2, flickity, flickity-imagesloaded, flickity-as-nav-for, flickity-fade, jarallax
I have identified two tasks here. First, I need to integrate the existing npm packages. Then I need to add the custom scripts.
Current status
1. Packages
I added the npm packages to ember-cli-build.js over app.import()
// ember-cli-build.js file
const EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function (defaults) {
let app = new EmberApp(defaults, {});
app.import("node_modules/bootstrap/dist/js/bootstrap.min.js");
app.import("node_modules/jarallax/dist/jarallax.min.js", {
using: [{ transformation: 'cjs', as: 'jarallax' }]
});
app.import("node_modules/flickity/dist/flickity.pkgd.min.js");
app.import("node_modules/flickity-as-nav-for/as-nav-for.js");
app.import("node_modules/flickity-fade/flickity-fade.js");
app.import("node_modules/flickity-imagesloaded/flickity-imagesloaded.js");
return app.toTree();
};
When I go to the debug tab in my browser I see the packages are getting loaded under assets/node_modules/.. but js does not have any effect.
I tried to load the package in index.html over a script tag:
<script type="text/javascript" src="{{rootURL}}assets/node_modules/flickity/dist/flickity.pkgd.min.js"></script>
I get the error in the browser console window:
Refused to execute http://localhost:4200/assets/node_modules/flickity/dist/flickity.pkgd.min.js as script because "X-Content-Type-Options: nosniff" was given and its Content-Type is not a script MIME type.
2. Custom js scripts
The custom scripts have a moin theme.js script that imports everything else.
// js/theme.js
// Theme
import './aos';
import './bigpicture';
// ...
The imported Javascript scripts from theme.js also have imports like
// js/aos.js (imported from theme.js)
import AOS from 'aos';
const options = {
duration: 700,
easing: 'ease-out-quad',
once: true,
startEvent: 'load'
};
AOS.init(options);
The original theme.js also had import for Bootstrap and the other libraries.
// js/theme.js
// Vendor
import 'bootstrap';
import 'flickity';
// ...
import 'jarallax';
// Theme
import './aos';
import './bigpicture';
// ...
I had the js directory under vendor, public and app the import via the script tag did not work either. Importing from app.js has no effect.
Related
I have an issue on which I struggled all day long, I have a VueJS app with vue router that I host on amplify?
everything working great Except that
I need to give a direct access to a file (I want to register an Apple merchant ID with stripe)
I tried to create a route in my route/index.js with my file name that redirect to a component that open the merchantid file with an windows.open('myfile').
it works great on local serve and build but not once deployed through amplify built with webpack
//router/index.js
import WellKnown from '#/components/AppleVerification.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/.well-known/apple-app-site-association',
component: WellKnown,
}
]
const router = new VueRouter({
mode: 'history',
routes
})
export default router
// AppleVerification.vue
<template>
<div></div>
</template>
<script>
export default {
name: 'WellKnown',
props: {
file: String
},
mounted () {
window.open('file:///.well-known/apple-developer-merchantid-domain-association')
}
}
</script>
so I went to amplify console and make a redirection with first priority to the URL and target address to the file. but it didn't work also.
I went out of ideas on how to give access to a file in my sources with a direct URL.
would appreciate a little help
thanks
You issue comes from the acces to the file througth Amplify for several reasons.
Try following:
rename your endfile "apple-developer-merchantid-domain-association"
with an extension like
apple-developer-merchantid-domain-association.txt
remove the dot in your path public/.well-known/apple-developer-merchantid-domain-association to public/well-known/apple-developer-merchantid-domain-association.txt
in your amplify console create a priority 1 rule that redirects your
https://mydomain/.well-known/apple-developer-merchantid-domain-association to
/well-known/apple-developer-merchantid-domain-association.txt with a 202 rexrite method.
It should work
You even didn't need the component anymore
I'm using a "core" ember addon in a boilerplate, with
npm link core-addon
This addon contains generic components, helpers, routes...
Is there a way to exclude some of these components in the boilerplate's ember-cli-build file?
I already tried the following in the ember-build-cli in my boilerplate project, which is probably wrong:
const EmberApp = require('ember-cli/lib/broccoli/ember-app');
const environment = EmberApp.env();
module.exports = function (defaults) {
let app = new EmberApp(defaults, {
funnel: {
enabled:true,
exclude:['core-addon/pods/components/pages/**/*']
},
});
return app.toTree();
};
Ember version: 3.5.0
Ember cli version 3.5.0 node version 8.11.3
Addons generally take the reverse approach of this: The addon manages what gets merged into the consuming app via configuration in the consuming app.
At the highest level, each addon has an entry point that is the index.js file sitting in the root directory of the addon. The addon provides certain configuration options that it reads from config/environment.js of the consuming app when installing.
I think a really good case study for you would be ember-bootstrap. Look at their configuration options and more specifically the blacklist option. They allow the consuming application to only install a subset of the bootstrap components. Furthermore, the project supports bootstrap 3 or bootstrap 4, but the consuming app isn't getting both! The work is done in index.js
Let's look just at how they blacklist (ie exclude) certain components from being added to the consuming app:
treeForApp(tree) {
tree = this.filterComponents(tree);
return this._super.treeForApp.call(this, tree);
},
filterComponents(tree) {
let whitelist = this.generateWhitelist(this.bootstrapOptions.whitelist);
let blacklist = this.bootstrapOptions.blacklist || [];
// exit early if no opts defined
if (whitelist.length === 0 && blacklist.length === 0) {
return tree;
}
return new Funnel(tree, {
exclude: [(name) => this.excludeComponent(name, whitelist, blacklist)]
});
}
where this.excludeComponent at it's core is a boolean returning filter function that returns true if the blacklist contains it in the blacklist case (there for excluding it). The treeForApp function returns the tree for all app files, ie what will be merged from the addon's app dir into the consuming app:
The consuming app's ember-cli-build would look something like this:
//your-bootstrap-app/ember-cli-build.js
module.exports = function(defaults) {
let app = new EmberApp(defaults, {
'ember-bootstrap': {
blacklist: ['bs-popover', 'bs-accordion']
}
});
return app.toTree();
};
and the result would be no bs-popover and no bs-accordion available in the consuming apps app tree. These options are obtained in the index.js file like so:
let options =Object.assign({}, defaultOptions, app.options['ember-bootstrap']);
this.bootstrapOptions = options;
Check this general guide to building addons and the more advanced api for more info.
I'm trying to set up hot module replacement for my bundled frontend static assets that are served through Django's template system, if that's even possible. I'm currently refreshing the page via livereload whenever the compiled assets are changed, but the compile times are getting longer and any CSS changes end up triggering a full page reload.
Here is an example of the template file in Django.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- Header Links -->
</head>
<body>
<div id="app"></div>
<script type="text/javascript">
window.CONFIG = {
/** Injected application configuration from Django. */
};
</script>
<!-- Webpack bundle url -->
<script src="{{ bundle_url }}"></script>
</body>
</html>
I've been able to serve the assets through webpack dev server and inject the bundle url http://localhost:3000/bundle.js through template variables, so I can see the application in the view.
Webpack Configuration
'use strict';
const webpack = require('webpack');
const CONFIG = require('./config');
/**
* Webpack configuration for a development environment.
* #type {Object}
*/
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: [
require.resolve('core-js/shim'),
CONFIG.PATHS.ENTRY,
],
output: {
path: CONFIG.PATHS.BUILD,
filename: CONFIG.OUTPUT_FILENAME,
},
module: {
rules: CONFIG.SHARED_RULES.concat([{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
}, {
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
}]),
},
resolve: CONFIG.WEBPACK_RESOLVE,
plugins: [
new webpack.HotModuleReplacementPlugin(),
],
};
Start Script:
'use strict';
// Crashes the script on unhandled rejections instead of silently ignoring.
process.on('unhandledRejection', (error) => { throw error; });
process.env.NODE_ENV = 'development';
// Vendor
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const chalk = require('chalk');
// Local
const WEBPACK_CONFIG = require('../config/webpack.config.dev');
const CONFIG = require('../config/config');
const PORT = parseInt(process.env.PORT, 10) || CONFIG.DEFAULT_PORT;
const HOST = process.env.HOST || CONFIG.DEFAULT_HOST;
const URL = `http://${HOST}:${PORT}/`;
const compiler = webpack(WEBPACK_CONFIG);
const server = new WebpackDevServer(compiler, {
compress: true,
hot: true,
host: HOST,
stats: 'minimal',
});
server.listen(PORT, HOST, (error) => {
if (error) { return console.log(chalk.red(error)); }
console.log(chalk.cyan(`Starting the development server at ${URL}...`));
['SIGINT', 'SIGTERM'].forEach((signal) => {
process.on(signal, () => {
server.close();
process.exit();
});
});
});
I'm uncertain how the dev server triggers a hot reload. I was under the impression that the bundle includes a script that connects to a Websocket connection on the dev server and that the connection would trigger the script to download and display the new assets. This may not be the case though, and I haven't been able to find any info pertaining to how hot reloads are communicated. I've only found a general overview of how hot reloads work once the client receives the update.
After a lot of searching, I finally found a solution to my problem. I found information about how to integrate webpack-dev-server with an existing server in the old webpack docs, so I got rid of the entire build script and replaced it with a script in package.json that only used webpack-dev-server without any flags at all:
"scripts": {
"start": "cross-env NODE_ENV=development webpack-dev-server",
// Scripts...
}
This automatically injected the hot module replacement code into my bundle and refreshes my page on a change. This is much faster than my previous livereload server. The bundle is referenced via the url http:localhost:8080/bundle.js in my application template and not by a local path. Local paths wouldn't work anyways since the bundles are saved in memory.
The url also explains how to get the --inline --hot functionality working too, but I was never able to get it to work on my setup.
If you need to use local path's instead of referencing the bundles via url, than you would have to rely on using webpack's watch mode and manually refreshing the page or rely on a Django plugin. The solution I found worked well for me because it mirrors our production environment. Our Django deployment references the frontend assets through a CDN that we manage. It may not work well for you if you have to deploy the frontend assets with your Django code, but it's possible if you create a Django setting that toggles between two different application templates: one for development that uses the URL to pull in the script and one for production that references the files from the STATICFILES_DIRS.
The problem I don't think is Webpack's fault. I've noticed these speed problems occur when I had Django serve my React files. When you use Django, your files are served by the Django server, and that inherently is pretty slow compared to the webpack-dev server. The whole communication process between webpack dev server to Django can be time taking, which has to have the Django server to trigger a change and then re-serve the static files again.
One solution to this would be to isolate React front end code from the backend code and have your React consume your Django's REST API. It runs extremely smooth and reduces a lot of load on the server.
I'd like to export PDF documents using jsPDF in an Ember app, but I can't figure out how to make the library available within the app.
So far, I've installed the library using bower:
bower.json
{
"name": "myApp",
"dependencies": {
...
"jspdf": "~1.2.61"
}
}
...and imported it in the ember-cli-build.js file:
ember-cli-build.js
...
app.import(app.bowerDirectory + '/jspdf/dist/jspdf.min.js');
...
However, when I try to use it (by calling var doc = new jsPDF() in an Ember action), I get this:
ReferenceError: jsPDF is not defined
What am I missing?
add your bower compoent here :
module.exports = function(defaults) {
....
app.import(app.bowerDirectory + '/jspdf/dist/jspdf.min.js'); // Your file
....
};
Try to change your code to :
actions:{
createPDF: function() {
var doc = new jsPDF(); // This part is your mistake
doc.text(20, 20, 'Hello world.');
doc.save('Test.pdf');
}
}
call your action for your button like
<button type="button" {{action "createPDF"}}>Create PDF</button>
and then Stop your Ember serve then again start it
Ember serve
that will work. when you add something to ember-cli-build.js you must stop and start your serve again .
Also for more information read this document : https://guides.emberjs.com/v2.7.0/addons-and-dependencies/managing-dependencies/
I'm using the ember-cli to build my app, which gives me a nice app.js file that I can server up on a static asset server. What is the most idiomatic way to allow for a separate configuration at deployment time?
For example, I might tell the consumer of my app.js file to include an extra config.[js|json] file which will get loaded, and the values from that file would go into the ENV object... so that I can point the app at a different REST endpoint, for example (QA, Sandbox, Pre-release, etc) without re-compiling.
I figure there must be a way, I'm just not seeing it. I get that there is the config/environment.js file, but that gets compiled into the dist folder. I'm looking for something that sits next to the packaged JS. I can certainly hack something together, so I'm not looking for a hack. An ember-cli-addon, perhaps? I figure there must be an "ember way" to do this.
I'm just not finding it :)
Ok, here is what I did. Basically, I allow some settings to be overridden by the host application. I register an initializer to jam them into the configuration object, and then I use the config options like normal. It looks a little something like this:
config/environment.js
// This is just normal ENV.APP configuration stuff. Nothing odd here
module.exports = function(environment) {
var ENV = {
// snip
APP: {
API_HOST: 'http://defaultAPIHost.com',
AUTH_PROVIDER: 'http://defaultAuthProvider.com'
}
};
return ENV;
};
app/initializers/parameter-overrides.js
import config from '../config/environment';
// This is the custom stuff. If the values have been defined globally,
// override them on the config object. I suppose this can be done a
// bit more dynamically, but this explicit code is for illustrative purposes.
export function initialize() {
let apiOverride = window.MyAppEnv && window.MyAppEnv.API_HOST;
let authOverride = window.MyAppEnv && window.MyAppEnv.AUTH_PROVIDER;
config.APP.API_HOST = apiOverride || config.APP.API_HOST;
config.APP.AUTH_PROVIDER = authOverride || config.APP.AUTH_PROVIDER;
}
export default {
name: 'parameter-overrides',
initialize: initialize
};
app/adapters/application
import DS from 'ember-data';
import config from '../config/environment';
// Then consume the config properties as you normally would
export default DS.RESTAdapter.extend({
host: config.APP.API_HOST,
namespace: "api"
});
Now, the hosting application can include this in the page, and it will override the values from the config/environment.js:
<script type="text/javascript">
// Override this value in production to the proper API host and Auth host
window.MyAppEnv = {
AUTH_PROVIDER: null, //'http://oauthhost.com/OAuth2'
API_HOST: null //"http://apihost.com"
};
</script>
Is this a reasonable approach? Is there something better out there?