How can I access a bower package as an ES6 module? - ember.js

I'm trying to migrate an ember app to use the ember app-kit. The code requires the accounting.js library. In the pre-app-kit version the file was loaded via a script tag in index.html
<script src="http://cdnjs.cloudflare.com/ajax/libs/accounting.js/0.3.2/accounting.min.js"></script>
and accessed in the views through the global namespace
App.MoneyField= Em.TextField.extend({
init: function() {
this._super();
var value = accounting.formatMoney(this.get("money") / 100, '');
this.set('value', value);
};
// other functions omitted
});
In the app-kit version, I've included accounting.js as a bower dependency. In bower.json:
{
"name": "ember-app-kit",
"dependencies": {
"handlebars": "~1.1.2",
"jquery": "~1.9.1",
"qunit": "~1.12.0",
"ember": "~1.4.0-beta.2",
"ember-data": "~1.0.0-beta.6",
"ember-resolver": "git://github.com/stefanpenner/ember-jj-abrams-resolver.git#master",
"ic-ajax": "~0.3.0",
"ember-testing-httpRespond": "~0.1.1",
"accounting":"~0.3.2"
},
"resolutions": {
"ember": "~1.4.0-beta.2"
}
}
When I try to build the app, it gives the error
W117: 'accounting' is not defined.
I understand why this is and know I need some sort of import accounting from ... statement.
How do I import a package installed via bower as an ES6 module?

I know that this was asked a few months ago, but since then, Ember App Kit has been succeeded by ember-cli, and this provides a very straight forward means to access either bower or npm dependencies.
Non-AMD asset
AMD asset
With regards to being accessed as ES6 modules:
Non-AMD assets cannot be accessed as an ES6 module, you simply access them through the global variable that they export.
e.g. moment
AMD assets, on the other hand, can be accessed through the ES6 import syntax
e.g. import { raw as icAjaxRaw } from 'ic-ajax';
Worth also mentioning, that ember-cli supports an add-on system now, which can make importing these things as simple as adding them to the package.json of your project. Some of the more popular libraries already have ember-cli addons for them. This post describes how you can write your own.

Related

Emberjs : how to import after 'npm install'

Trying to use howler.js (https://github.com/goldfire/howler.js#documentation) in a Controller.
There is no addon for Howler but it exists as a npm package.
I did an npm install and subsequently got an update in package.json like this :
"dependencies": {
"bootswatch": "^4.0.0",
"howler": "^2.0.9",
"npm": "^5.8.0"
}
In the controller I added this import
import {Howl} from 'howler';
But when I try to execute the code I get a runtime error
Could not find module 'howler' imported from 'foo/controllers/bar'
When I do a find for *howl* this is what I find
./node_modules/howler/dist/howler.js
./node_modules/howler/dist/howler.core.min.js
./node_modules/howler/dist/howler.min.js
./node_modules/howler/dist/howler.spatial.min.js
./node_modules/howler/src/howler.core.js
./node_modules/howler/src/plugins/howler.spatial.js
Should my import have a path to these files as part of it ? If so which one ?
Would appreciate some advice about whether there's something obviously wrong in what I've done there.
Emberjs version is 3.0.
Thanks
You can import the howler.js inside your ember-cli-build.js like this
app.import('node_modules/howler/dist/howler.min.js')
Then you can use Howl as global variable inside you ember app.

Django Webpack compiling misc JS in brand new Django/ReactJS app to make 21,500 line file

I have been following the below tutorial to get Django and ReactJS working:
http://geezhawk.github.io/using-react-with-django-rest-framework
I started a brand new Django project, added an app called home, but have otherwise done nothing else except what is outlined in the tutorial.
Anyway, when I compile the JS it creates a file that is about 21,500 lines and 800kb. My ReactJS file is only about 20 lines and there is no other JS to speak of from the Django app. It seems like it is compiling dependencies in the virtualenv or something. Anyway to prevent this?
webpack.config.js
//require our dependencies
var path = require('path')
var webpack = require('webpack')
var BundleTracker = require('webpack-bundle-tracker')
module.exports = {
//the base directory (absolute path) for resolving the entry option
context: __dirname,
//the entry point we created earlier. Note that './' means
//your current directory. You don't have to specify the extension now,
//because you will specify extensions later in the `resolve` section
entry: './assets/js/index',
output: {
//where you want your compiled bundle to be stored
path: path.resolve('./assets/bundles/'),
//naming convention webpack should use for your files
filename: '[name]-[hash].js',
},
plugins: [
//tells webpack where to store data about your bundles.
new BundleTracker({filename: './webpack-stats.json'}),
//makes jQuery available in every module
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
})
],
module: {
loaders: [
//a regexp that tells webpack use the following loaders on all
//.js and .jsx files
{test: /\.jsx?$/,
//we definitely don't want babel to transpile all the files in
//node_modules. That would take a long time.
exclude: /node_modules/,
//use the babel loader
loader: 'babel-loader',
query: {
//specify that we will be dealing with React code
presets: ['react']
}
}
]
},
resolve: {
//tells webpack where to look for modules
modulesDirectories: ['node_modules'],
//extensions that should be used to resolve modules
extensions: ['', '.js', '.jsx']
}
}
A couple of things
React and jQuery are part of your bundle. Yes you only wrote ~20 lines of code, but you are also importing React into your project, and since you only have one entry defined, everything you import will get bundled into a single bundle (which may be fine for your needs). What's more, your Webpack config also imports jQuery globally. You can break dependencies up into their own bundle or into multiple bundles and load them on demand if needed.
You are bundling the development version of React. When Webpack runs and bundles your project it will do different things based on whether process.env evaluates to "development" or "production". The idea being to make development easier and build times faster during development. In the case of React, you are getting its development version with lots of comments and extra checks (more kilobytes) simply because your environment isn't set to "production".
Tree shaking, deduping, and minification are your friends. I'll let you look into these, but basically, tree shaking (part of Webpack 2) makes it so you only bundle the part of a library you actually use. In webpack 1.x, there's a deduping plugin that will remove duplicate sections of code, and minification will, well, minify your code. You can setup your Webpack config to run these steps only when being run in a production build environment.
Try swapping your plugins section out with this to start:
plugins: [
...(process.env === 'production' ? [
// set webpack process env to production
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify('production') },
}),
new webpack.optimize.DedupePlugin(), // webpack 1.x only
new webpack.optimize.UglifyJsPlugin({ comments: false }),
] : []),
//tells webpack where to store data about your bundles.
new BundleTracker({filename: './webpack-stats.json'}),
//makes jQuery available in every module
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
}),
],

Setting up UserApp.io on ember-cli

This may seem trivial, but I have been unsuccessful at getting this to work. I have used UserApp.io successfully for user/authentication management. I recently created an ember app using ember-cli, but I am unable to get the two to work together despite ember being supported by UserApp.io. Here are there instructions (integrating with ember without cli).
https://github.com/userapp-io/userapp-ember
Here is a snippet:
Include the UserApp JavaScript library and this Ember module in your index.html. Be sure to add them before your app.js file.
<script src="https://app.userapp.io/js/userapp.client.js"></script>
<script src="https://app.userapp.io/js/ember-userapp.js"></script>
(You can also install the module with bower: $ bower install userapp-ember)
Initiate the module
Add this code above App = Ember.Application.create(); in app.js with your App Id.
Ember.Application.initializer({
name: 'userapp',
initialize: function(container, application) {
Ember.UserApp.setup(application, { appId: 'YOUR-USERAPP-APP-ID' });
}
});
Because I am using ember-cli I have created a file called userapp.js in an initializers folder which has the following code:
import Ember from 'ember';
export default {
name: 'userapp',
initialize: function(container, application) {
Ember.UserApp.setup(application, {
appId: 'USERAPP-ID-INSERTED-HERE',
loginRoute: 'login',
indexRoute: 'index',
heartbeatInterval: 20000,
usernameIsEmail: false
});
}
};
When I run my app I get the following error:
Uncaught TypeError: Cannot read property 'setup' of undefined
I feel like this is something simple/stupid, but for the life of me I cannot figure this one out.
It seems ember-userapp.js is not getting included in ur app. If you are using bower to install it, edit the Brocfile.js to include the lib like
app.import('bower_components/userapp-ember/ember-userapp.js');
Its mentioned here http://ember-cli.com/#standard-non-amd-asset

How to use third party npm packages with ember cli app

EDIT: this is actually about any npm package which is not designed to play along with ember. In my case, I tried to make crypto-js work, but it seems to be always the same trouble with any npm package not specially designed for ember cli.
I want to use cryptoJS in my ember app, which I'm currently refactoring with ember cli, but I'm having a lot of trouble importing all the third party packages and libraries I'm already using, like for example cryptoJS.
CryptoJS at least has a package for npm, I don't even want to think about what happens if some of my included libraries don't have a package...
Am I just missing the point in the documentation of ember-cli or is it really not described how to import other npm packages and also how to inlcude non-package libraries properly to keep them under version control and dependency control?
If I follow the description of the crypto-js package manual:
var CryptoJS = require("crypto-js");
console.log(CryptoJS.HmacSHA1("Message", "Key"));
I get and error in my ember build
utils/customauthorizer.js: line 1, col 16, 'require' is not defined.
Thanks for any help on this, I'm very excited about the ember cli project, but importing my existing ember app has been quite painful so far...
EDIT:
Just importing unfortunately does not work.
import CryptoJS from 'crypto-js';
throws during the build
daily#dev1:~/VMD$ ember build
version: 0.1.2
Build failed.
File: vmd/utils/customauthorizer.js
ENOENT, no such file or directory '/home/daily/VMD/tmp/tree_merger-tmp_dest_dir-F7mfDQyP.tmp/crypto-js.js'
Error: ENOENT, no such file or directory '/home/daily/VMD/tmp/tree_merger-tmp_dest_dir-F7mfDQyP.tmp/crypto-js.js'
at Error (native)
at Object.fs.statSync (fs.js:721:18)
at addModule (/home/daily/VMD/node_modules/ember-cli/node_modules/broccoli-es6-concatenator/index.js:84:46)
at addModule (/home/daily/VMD/node_modules/ember-cli/node_modules/broccoli-es6-concatenator/index.js:133:9)
at addModule (/home/daily/VMD/node_modules/ember-cli/node_modules/broccoli-es6-concatenator/index.js:133:9)
at /home/daily/VMD/node_modules/ember-cli/node_modules/broccoli-es6-concatenator/index.js:59:7
at $$$internal$$tryCatch (/home/daily/VMD/node_modules/ember-cli/node_modules/rsvp/dist/rsvp.js:470:16)
at $$$internal$$invokeCallback (/home/daily/VMD/node_modules/ember-cli/node_modules/rsvp/dist/rsvp.js:482:17)
at $$$internal$$publish (/home/daily/VMD/node_modules/ember-cli/node_modules/rsvp/dist/rsvp.js:453:11)
at $$rsvp$asap$$flush (/home/daily/VMD/node_modules/ember-cli/node_modules/rsvp/dist/rsvp.js:1531:9)
The easiest and recommended answer is to use ember-browserify. (as support for bower packages will be removed in the future.)
This is an example for using the npm package dexie within an Ember CLI app.
Install browserify: npm install ember-browserify --save-dev
Install dexie (or whatever module you need): npm install dexie --save-dev
Import the module like this: import Dexie from 'npm:dexie';
UPDATE (April 2021):
ember-browserify has now been is deprecated in favor of either ember-auto-import or ember-cli-cjs-transform
(see the deprecation warning at the top of ember-browserify)
UPDATE: I got this to work much better and straight forward! Thanks to the comment of #j_mcnally!
Will leave the first answer down there so everyone can see what trouble I was coming from :)
What I did:
bower install crypto-js=svn+http://crypto-js.googlecode.com/svn/#~3.1.2 --save
In my file Brocfile.js I could just do app.import('bower_components/crypto-js/build/rollups/hmac-md5.js');
No manual downloading or moving files, just managing a dependency, much better solution!
But honestly, it was still a lot of vodoo! Until I found the documentation... sweet: http://bower.io/docs/api/#install
OLD approach
I got this to work, but I can not tell how pretty or correct that approach is. Including third party packages or libraries with ember cli is pretty far away from straight forward or self explaining.
The ressources which led me to my working solution were:
how to use third party javascript from ember-cli route
https://github.com/stefanpenner/ember-cli/issues/757
The following steps I took to get it working:
I manually downloaded the library https://code.google.com/p/crypto-js/downloads/detail?name=CryptoJS%20v3.1.2.zip and unziped it
I manually created a directory in my vendor directory: mkdir vendor/crypto-js
I appended app.import('vendor/crypto-js/hmac-md5.js'); to the Brocfile.js file
I added "CryptoJS" to the "predef" key in the .jshintrc file
Then the build worked and I could eventually use the library.
Sadly I didn't get the npm package to work! I had to manually download the zip file, unzip it and move it to the correct location and if the version changes, it's not under any version/dependency control... I will not mark this as an answer, since it does not satisfy me at all, but at least I wanted to share what I did to make it work for me.
As Timm describes, using browserify gets the code injected into your ember app. However, I was having trouble actually using the injected module. In order to do that I had to actually create the module with New before I could use it:
In order to import an NPM module.
1) install browserify:
npm install ember-browserify --save-dev
2) install your modele:
npm install my-module --save-dev
3) Import your module into your ember file of interest (app/controller/post.js):
import Module from 'npm:my-module';
4) use the module from within your code by creating the module with New:
var output = new Module(var1, var2, etc.);
even though this is an old thread thought I would contribute as I spent a while doing this. The specific package I was trying to link to ember was 'd3plus' and had to do a variety of things to get it to work.
npm install ember-browserify --save-dev
npm install d3plus --save-dev
ember install ember-cli-coffeescript
npm install --save-dev coffeeify coffeescript
then in your component do
import d3plus from 'npm:d3plus';
For a long time I was getting runtime errors when it was searching for the coffescript and figured this would be helpful for people specifically looking for d3plus.
As stated by Pablo Morra on a comment of the simplabs' post "Using npm libraries in Ember CLI", third party npm modules can be imported on Ember.js from version 2.15 directly without the need of addons or wrappers:
https://www.emberjs.com/blog/2017/09/01/ember-2-15-released.html#toc_app-import-files-within-node_modules
Unfortunately documentation is still on work and it doesn't say that npm modules can be imported, only bower and vendor ones:
https://github.com/emberjs/guides/issues/2017
https://guides.emberjs.com/v3.0.0/addons-and-dependencies/managing-dependencies/
I've gotten 2 solutions to import third party npm modules directly on Ember.js from the Ember CLI documentation about managing dependencies, although it's also out-of-date and says that npm modules can't be imported, only bower and vendor ones:
npm module as Standard Anonymous AMD Asset
https://ember-cli.com/managing-dependencies#standard-anonymous-amd-asset
AMD: Asynchronous Module Definition
I prefer and use this way because it avoids global variables and follows the import convention of Ember.js.
ember-cli-build.js:
app.import('node_modules/ic-ajax/dist/amd/main.js', {
using: [
{ transformation: 'amd', as: 'ic-ajax' }
]
});
amd is the type of transformation applied, and ic-ajax is the module name to be used when it's imported on a javascript file.
on Ember.js javascript file (router, component...):
import raw from 'ic-ajax';
// ...
icAjaxRaw( /* ... */ );
raw is a module exported by ic-ajax.
That's the way it worked for me although the Ember CLI documentation shows the import other way that didn't work for me, maybe because of the specific package I was importing:
import { raw as icAjaxRaw } from 'ic-ajax';
//...
icAjaxRaw( /* ... */ );
npm module as global variable
https://ember-cli.com/managing-dependencies#standard-non-amd-asset
ember-cli-build.js:
app.import('node_modules/moment/moment.js');
on Ember.js javascript file (router, component...):
/* global moment */
// No import for moment, it's a global called `moment`
// ...
var day = moment('Dec 25, 1995');
/* global moment */ is an annotation for ESLint not to show an error when building the project because moment() is not defined in the file.
npm module as Standard Named AMD Asset
https://ember-cli.com/managing-dependencies#standard-named-amd-asset
Ember CLI also shows a third option that didn't work for me, maybe because of the specific package I was importing:
ember-cli-build.js:
app.import('node_modules/ic-ajax/dist/named-amd/main.js');
on Ember.js javascript file (router, component...):
import { raw as icAjaxRaw } from 'ic-ajax';
//...
icAjaxRaw( /* ... */ );
npm module as AMD JavaScript modules
https://guides.emberjs.com/v3.0.0/addons-and-dependencies/managing-dependencies/#toc_amd-javascript-modules
The way described on Ember.js documentation about Managing Dependencies didn't work for me either, maybe because of the specific package I was importing:
ember-cli-build.js:
app.import('node_modules/ic-ajax/dist/named-amd/main.js', {
exports: {
'ic-ajax': [
'default',
'defineFixture',
'lookupFixture',
'raw',
'request'
]
}
});
on Ember.js javascript file (router, component...):
import { raw as icAjaxRaw } from 'ic-ajax';
//...
icAjaxRaw( /* ... */ );

ember-cli 0.0.37 import new syntax and ember-data

I've recently upgraded from ember-cli 0.0.36 to 0.0.37 and have been struggling to import ember-data. Although seemingly simple, it's not working for me. In the Brocfile.js, the old import was
app.import({
development: 'vendor/ember-data/ember-data.js',
production: 'vendor/ember-data/ember-data.prod.js'
});
This was modified to comply with the new syntax:
app.import('vendor/ember-data/ember-data.js', { exports: { ember: ['default'] } });
however, I get the following error:
app.import(vendor/ember-data/ember-data.js) - Passing modules object is deprecated. Please pass an option object with modules as export key (see http://git.io/H1GsPw for more info).
I'm not sure how to proceed with this one so any help is much appreciated.
The new syntax is detailed here
As mentioned in the deprecated message this is the new syntax.
app.import({
development: 'vendor/ember-data/ember-data.js',
production: 'vendor/ember-data/ember-data.prod.js'
}, {
exports: {
'ember-data': ['default']
}
});
This error message was the result of leftovers from the old ember-cli-ember-data shim which was set to version 0.0.4 in the package.json file. I've changed it to 0.1.0 which is the latest as of this writing, removed (deleted) the old ember-cli-ember-data directory from the node_modules package directory and reran npm install. This resulted in the warning message disappearing.