How to import an amd module in ember-cli? - ember-cli

I am building an EmberJS application with the great help of ember-cli, which is great, but I have an error and I cannot find what I am doing wrong.
Here is what I do in my broccoli file:
app.import('vendor/underscore/underscore.js', {
exports: {
"underscore": [
"underscore"
]
}
});
and then in one of my controllers:
import _ from "underscore";
ember-cli builds my application.
But when I go to the controller using underscore, I get the error:
Error: Could not find module underscore.
What am I doing wrong?

Try:
app.import({
development: 'vendor/underscore/underscore.js',
production: 'vendor/underscore/underscore.min.js'
}, {
'underscore': [
'default'
]
});
This will at least give "import _ from 'underscore';" a chance to work. If you choose an AMD or ES6 version of underscore/lodash, list which modules you wish to import with 'default'.
EDIT:
Is it crucial that you use underscore? Why I ask, I'm using lodash with one Ember-cli project, and it is working fine.
Console> bower install lodash --save
then in Brocfile:
app.import({
development: 'vendor/lodash/dist/lodash.js',
production: 'vendor/lodash/dist/lodash.min.js'
}, {
'lodash': [
'default'
]
});
//or:
app.import('vendor/lodash/dist/lodash.min.js');
As for underscore - there was an issue with devDependencies not being bundled, of which underscore is one.

I got this from locks on #emberjs IRC.
https://github.com/ef4/ember-browserify
In your project:
npm install --save-dev ember-browserify
npm install --save-dev underscore
In your controller:
import _ from "npm:underscore";
Then you can use _. For example: _.each([1,2,3], alert);. I took everything out I had manually added to brocfile and package.json. Apparently this will do it for you. Crazy!

In recent versions of ember (I am using 2.11) it is possible to load AMD in UMD wrappers using
app.import('bower_components/js-md5/js/md5.js', {using: [{
transformation: 'amd', as: 'js-md5'
}]});
And in your code
import md5 from 'js-md5';
In your case of underscore it should look like:
app.import('vendor/underscore/underscore.js', {using: [{
transformation: 'amd', as: 'underscore'
}]});

Related

Not able to use babel "preset-env" plugin with NextJS

I have a requirement where I am trying to use the Babel plugin "preset-env". This plugin compiles my NextJS project from ES6 to ES5. I have created the .babelrlc file as suggested by NextJS documentation and added my plugin like this:
{
"presets": ["next/babel"],
"plugins": ["#babel/preset-env"]
}
When I try to run my project locally I get this error:
error - ./node_modules/next/dist/client/router.js
Error: Cannot find module '#babel/plugin-preset-env' from '/Users/agastya/Local/testcap/Sample-proj'
- If you want to resolve "#babel/preset-env", use "module:#babel/preset-env"
- Did you accidentally pass a preset as a plugin?
NextJS documentation says "Next.js includes the next/babel preset to your app, which includes everything needed to compile React applications and server-side code. ".
It would be great if someone can explain where/what is the right approach to fix this.
You have to do the following:
// .babelrc file, also could be babel.config.js
{
"presets": [
[
"next/babel",
{
"preset-env": {},
"transform-runtime": {},
"styled-jsx": {},
"class-properties": {}
}
]
],
"plugins": []
}
Taken from: https://nextjs.org/docs/advanced-features/customizing-babel-config

import with jest error: Unexpected token import

I've seen similar questions but still can't find a viable solution.
I'm trying to integrate Jest into a working project, which uses import/export default in hundreds of places. The following test does work for Jest using require:
const bar = require('../../flows/foo');
test('adds 1 + 2 to equal 3', () => {
expect(bar.foobar(1, 2)).toBe(3);
});
when export is:
module.exports = {
foobar: foobar,
fizz: fizz
}
The functions I'll want to be testing however are exported using:
export default {
foobar: foobar,
fizz: fizz
};
So when I try to update my test to import:
import foobar from '../../flows/foo';
With export:
export default {foobar: foobar};
I get the error
SyntaxError: Unexpected token import
All it takes:
// run this command (or npm equivalent)
yarn add #babel/core #babel/preset-env
// add babel.config.js
module.exports = {
presets: [
[
'#babel/preset-env',
{
targets: {
node: 'current'
}
}
]
]
};
Jest automatically picks it up, no other configuration required.
You have not set up a .babelrc file in your project, so transpiling is not happening. You need to transpile the ES6+ syntax (import, export, etc) into browser readable ES5.
I ran into this and solved it this way thanks to this GitHub issue post:
If you're using babel to transpile your code then remember to use the transform-es2015-modules-commonjs plugin.
To use it, you'll need to:
Install the plugin for BabelJS by entering this command in the CLI:
npm install --save-dev babel-plugin-transform-es2015-modules-commonjs
Add the plugin to your list of plugins in your babel config
plugins: [
"transform-es2015-modules-commonjs"
]

vscode automatic type acquisition for jest

I have vscode 1.9 and I want to have intellisense for jest tests. The problem is that describe, it, expect etc are globally available in jest and you don't need to import them in your test files. So vscode will not show intellisense for them.
Is there any configuration for globals for automatic type acquisition?
You have a few options in this case:
Add jest to your package.json:
"dependencies": {
"jest": "^18.1.0"
}
This only works if you are working JavaScript and do not have a tsconfig.json.
Install #types/jest
$ npm install -D #types/jest
This should work for both JavaScript and TypeScript projects. However #types but may be disabled by a jsconfig.json/tsconfig.json: http://www.typescriptlang.org/docs/handbook/tsconfig-json.html
Create a jsconfig.json file in the root of your workspace to specifically include jest:
{
"typeAcquisition": {
"include": [
"jest"
]
}
}
This will only work for JavaScript projects when automatic typings acquisition is enabled.
All of these should allow VSCode to pick up jest's typings without an import or require
I tried installing the #types/jest, and it did work, but the problem is that it resulted in the jest suggestions appearing in my .js files as well. I couldn't figure out how to get global suggestions for test, expect, etc. in only .test.js files but not .js files.
So I decided to just manually import each jest global I was going to use in each .test.js file, which allowed the suggestions to appear with types but avoided having the suggestions appear in the .js files:
import { test, expect } from '#jest/globals'
npm install -D #types/jest
edit jest.config.js
typeAcquisition: {
include: ['jest'],
},

babel-jest doesn't handle ES6 within modules

I am trying to set up Jest on a React based project which uses ES6 modules. However I seem to be having issues with ES6 modules, I am using babel-jest and believe I have this set up properly (Jest detects it automatically).
Jest doesn't seem to have a problem using ES6 imports however as soon as it hits on an import statement within one of the imported modules it chokes. It's as if it is only transpiling the initial test script and not any of the imported modules. I have tried various configurations and tried searching Google with no luck. Running tests without any imports works fine.
Here is the error:
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import Predications from './predications';
^^^^^^
SyntaxError: Unexpected token import
Here are the relevant bits of config:
jest.conf.json
{
"testRegex": "\/test\/spec\/.*\\.js$",
}
.babelrc
{
"presets": ["es2015", "stage-0", "react"]
}
Test script
import React from 'react';
import { mount, shallow } from 'enzyme';
import Slider from 'react-slick';
import Carousel from '../../client/components/carousel/carousel.js'; // test chokes on when I include this module
describe('carousel component', () => {
it('is a test test case', () => {
expect(1 + 2).toEqual(3);
});
});
Update:
As suggested, I have tried running the test without jest.conf.js, however the testRegex is needed in order for Jest to find my tests, I tried moving tests to the default test directory and they still fail.
I would like to clarify that tests themselves are running fine, the issue seems to be where one of my imported modules uses ES6, in my example above, if I don't import my carousel component the test runs fine, as soon as I import that the test chokes on the import statement within that file. It seems as though the imported modules are not getting transpiled.
Update #2
After some investigation it appears the issue is that babel is not transpiling ES6 within node_modules. I have created an example repo to demonstrate this here: https://github.com/jamiedust/babel-jest-example
I understand that third party modules should be handling their own transpiling, however we have a number of modules which are hosted on our own npm registry and are re-used between projects, in these cases Webpack handles transpiling, for the Jest tests we need these node_modules to be transpiled by Babel, or a way of leveraging our webpack set up to do this for us.
Solution
Add the following config in package.json (or Jest config file).
"jest": {
"transformIgnorePatterns": [
"/node_modules/(?!test-component).+\\.js$"
]
}
By default any code in node_modules is ignored by babel-jest, see the Jest config option transformIgnorePatterns. I've also created a PR on your example repo, so you can see it working.
While this works, I've found it to be extremely slow in real applications that have a lot of dependencies containing ES modules. The Jest codebase has a slightly different approach to this as you can find in babel-jest transforming dependencies. This can also take much longer on Windows, see Taking 10 seconds on an empty repo.
If doing "unit" testing, mocking is probably the better way to go.
You could try adding the transform-es2015-modules-commonjs plugin to your babel config file for testing only. Here is an example config file which tells babel to transpile modules only when in a testing environment. You can put it underneath your presets:
{
"presets": [
"react",
["es2015", {"modules": false, "loose": true}]
],
"env": {
"test": {
"plugins": ["transform-es2015-modules-commonjs"]
}
}
}
You can read about the plugin here:
https://www.npmjs.com/package/babel-plugin-transform-es2015-modules-commonjs
Then, when running your Jest tests on the command line specify NODE_ENV=test (you may need to add the --no-cache flag to the command the first time after making the change to the babel config because Jest caches babel output, but after that you can leave it off:
NODE_ENV=test jest --no-cache
I learned about this issue in a React seminar by Brian Holt at Frontend Masters. https://frontendmasters.com/courses/
faced the same issue, followed the steps to resolve,
install babel-jest
in jest config add this configuration
transform: {
'^.+\\.js?$': require.resolve('babel-jest')
}
make sure you have babel.config.js present (your config might be different than provided below)
module.exports = {
"env": {
"test": {
presets: [
[
'#babel/preset-env',
{
targets: {
node: 'current',
},
},
],
]
}
}
};
I faced the same problem (node_module not transpiled by babel-jest), without being able to solve it.
Instead, I finally succeed by mocking the node_module, like described here https://facebook.github.io/jest/docs/manual-mocks.html
NB: setting mocks in __mocks__ subfolders did not work for me. So I passed the mock as the second parameter of the jest.mock() function. Something like :
jest.mock('your_node_module', () => {})
Another possible cause. Babel now ignores your .babelrc inside node_modules and uses the one provided by the dependency. If you have control of the dependency you would have to add a .babelrc to it and babel would use those settings for it.
this can cause problems though if your dependency and your project use different babel versions or modules.

How to use blueimp-file-upload with webpack?

I'm using blueimp-file-upload in my website, and I'm using webpack to organize my js code.
I installed blueimp-file-upload and jquery.ui.widget from NPM
npm install --save blueimp-file-upload
npm install --save jquery.ui.widget
and I require blueimp-file-upload in my entry file
require('blueimp-file-upload')
but when I run webpack, I get thie error:
ERROR in ./~/blueimp-file-upload/js/jquery.fileupload.js
Module not found: Error: Cannot resolve module 'jquery.ui.widget' in E:\app-parent\cooka-common-web\src\main\resources\static\node_modules\blueimp-file-upload\js
# ./~/blueimp-file-upload/js/jquery.fileupload.js 19:8-22:19
If you're working with images:
Webpack was complaining about some modules that weren't in the blueimp-file-upload package. Here is the way I got this working:
Install missing dependencies:
npm i -S blueimp-load-image
npm i -S blueimp-canvas-to-blob
Configure Webpack:
config.resolve = {
extensions: ['', '.js'],
alias: {
'load-image': 'blueimp-load-image/js/load-image.js',
'load-image-meta': 'blueimp-load-image/js/load-image-meta.js',
'load-image-exif': 'blueimp-load-image/js/load-image-exif.js',
'canvas-to-blob': 'blueimp-canvas-to-blob/js/canvas-to-blob.js',
'jquery-ui/widget': 'blueimp-file-upload/js/vendor/jquery.ui.widget.js'
}
};
Include scripts in your app:
import "blueimp-file-upload/js/vendor/jquery.ui.widget.js";
import "blueimp-file-upload/js/jquery.iframe-transport.js";
import "blueimp-file-upload/js/jquery.fileupload.js";
import "blueimp-file-upload/js/jquery.fileupload-image.js";
Disable both AMD and CommonJS and use the Browser Global jQuery.
/* The jQuery UI widget factory, can be omitted if jQuery UI is already included */
require('imports?define=>false&exports=>false!blueimp-file-upload/js/vendor/jquery.ui.widget.js');
/* The Iframe Transport is required for browsers without support for XHR file uploads */
require('imports?define=>false&exports=>false!blueimp-file-upload/js/jquery.iframe-transport.js');
/* The basic File Upload plugin */
require('imports?define=>false&exports=>false!blueimp-file-upload/js/jquery.fileupload.js');
/* The File Upload processing plugin */
require('imports?define=>false&exports=>false!blueimp-file-upload/js/jquery.fileupload-process.js');
/* The File Upload validation plugin */
require('imports?define=>false&exports=>false!blueimp-file-upload/js/jquery.fileupload-validate.js');
/* The File Upload Angular JS module */
require('imports?define=>false&exports=>false!blueimp-file-upload/js/jquery.fileupload-angular.js');
This is the configuration I'm using to integrate webpack, blueimp-fileupload with angular. Alternatively you can configure in your webpack.config.js as a regex to avoid repeating loaders.
resolve: {
extensions: ['', '.js'],
alias: {
'jquery-ui/widget': 'blueimp-file-upload/js/vendor/jquery.ui.widget.js'
}
}
I had almost identical problem, except that Error announced not 'jquery.ui.widget' but 'jquery/ui/widget'.
For me #Gowrav answer was wrong way.
After days of straying I've solved it in the simple way. Just did:
npm install jquery-ui
The fact is that jquery.fileupload.js searching for its vendor:
But in context where jquery.fileupload.js is trying to import dependency, of course, it can't be found (resolved). So I add it to project instead.
P.S. It's just my opinion about how does all work. But this way has helped me.
jquery.fileupload.js checks for AMD require first which results in this error. You can teach webpack not to use AMD style for this file. (Make sure to npm install imports-loader for this method to work.):
require('imports?define=>false!blueimp-file-upload')
It should correctly register the module as CommonJS and will require the jquery.ui.widget from the right location.
Read more here: http://webpack.github.io/docs/shimming-modules.html#disable-some-module-styles
You can add an alias to jquery.ui.widget's main file - it unfortunately doesn't specify one in its package.json, so webpack can't find it otherwise.
resolve: {
alias: {
"jquery.ui.widget": "node_modules/jquery.ui.widget/jquery.ui.widget.js"
}
},
first install two plugins
npm i blueimp-file-upload --save
npm i jquery-ui --save
then require in web pack
require('blueimp-file-upload/js/jquery.fileupload')
actually you can solve this by changing your webpack config, just add the path to resolve (for example I am using bower)
resolve: {
extensions: [ '', '.js', '.jsx' ],
modulesDirectories: [
'node_modules',
'bower_components',
'bower_components/blueimp-file-upload/js/vendor'
]
}
In webpack 3.x, the syntax will look like this:
{
test: require.resolve("blueimp-file-upload"),
use: "imports-loader?define=>false"
}