如何在 Ember CLI 应用中使用第三方的 npm 包

33

编辑:实际上这是关于任何不是专门为Ember设计的npm包。在我的情况下,我试图让crypto-js正常工作,但似乎任何不是专门为ember cli设计的npm包都会遇到相同的问题。

我想在我正在使用ember cli重构的应用中使用cryptoJS,但我在导入所有第三方包和库时遇到了很多麻烦,比如cryptoJS。

CryptoJS至少有一个用于npm的软件包,如果我的一些已包含的库没有软件包,我甚至不想去想...

我是不是只是在忽略ember-cli文档中的重点,或者确实没有描述如何正确导入其他npm软件包以及如何正确地包含非软件包库以使它们保持在版本控制和依赖控制之下?

如果我按照crypto-js软件包手册的说明进行操作:

var CryptoJS = require("crypto-js");
console.log(CryptoJS.HmacSHA1("Message", "Key"));

在我的ember build中出现了错误。

utils/customauthorizer.js: line 1, col 16, 'require' is not defined.

感谢任何关于此事的帮助,我对ember cli项目非常兴奋,但是迄今为止导入我的现有ember应用程序相当痛苦...

编辑:

仅仅导入是行不通的。

import CryptoJS from 'crypto-js';

编译过程中抛出异常

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)

Ember CLI使用ES6模块,要使用它,您需要import CryptoJs from 'crypto-js'; - Patsy Issa
是的,那不起作用...我最初也认为它应该像那样工作... :( 可能只是一个错误的路径,但有没有办法找出来呢?我更新了我的答案,感谢你的帮助! - Preexo
我也遇到了这个问题。当我查看tmp文件夹时,我发现broccoli没有将我的npm包包含在供应商树中。但是我的bower或vendor目录中的任何内容都有。 - antony
@antony:是的,当我手动将第三方库添加到供应商目录时,我也注意到了这一点...请参见下面的答案。我仍然希望有人能提出一个简单明了的解决方案,让我感到自己太蠢了,没有找到它;) - Preexo
1
@antony:我认为像我在下面回答中描述的“bower-way”是正确的方法……不过不是使用npm包,而是git仓库。据我所知,只有当npm包实际上是为ember cli制作时才适合安装npm包。 - Preexo
5个回答

59
最简单且建议使用ember-browserify。(因为支持bower包的功能将来会被移除。)
这是在Ember CLI应用中使用npm包dexie的示例。
安装browserify:npm install ember-browserify --save-dev 安装dexie(或您需要的任何模块):npm install dexie --save-dev 像这样导入模块:import Dexie from 'npm:dexie';

更新(2021年4月):

现在ember-browserify已经被弃用,建议使用ember-auto-importember-cli-cjs-transform

(请参见ember-browserify顶部的警告信息


6

更新: 我找到了更好、直接的方法! 感谢 @j_mcnally 的评论!

我将保留下面的第一个答案,以便大家了解我遇到的问题 :)

我的操作步骤:

bower install crypto-js=svn+http://crypto-js.googlecode.com/svn/#~3.1.2 --save

在我的文件Brocfile.js中,我只需要执行app.import('bower_components/crypto-js/build/rollups/hmac-md5.js');

没有手动下载或移动文件,只需管理依赖项,这是更好的解决方案!

但说实话,它仍然有很多“巫术”!直到我找到文档......太棒了:http://bower.io/docs/api/#install


旧方法

我让这个工作了,但我无法确定这种方法是否优雅或正确。在ember cli中包含第三方包或库与直接或自我解释相距甚远。

引导我找到有效解决方案的资源包括:

我采取了以下步骤才使它工作:

然后编译就可以了,我最终可以使用这个库了。

可悲的是,我无法让npm包起作用!我必须手动下载zip文件,解压缩并将其移动到正确的位置,如果版本更改,它不受任何版本/依赖控制......我不会将其标记为答案,因为它根本不能让我满意,但至少我想分享一下我所做的工作。


使用Bower获取JS文件,而不是手动将其包含在供应商中。 供应商应从Git中排除,Bower应管理安装。 - j_mcnally
谢谢你的提示!听起来更像是我真正想要做的事情!我相信如果你把那个变成通用的答案,不仅我会受益匪浅...不过我自己会尝试一下,只是还没有接触过 Bower ;) - Preexo
1
将"CryptoJS"添加到.jshintrc文件中的"predef"键仍然需要,直到Ember 1.10.0,否则JSHint会在控制台中报错。 - poweratom

2

正如Timm所描述的那样,使用browserify可以将代码注入到您的ember应用程序中。然而,我在实际使用注入的模块时遇到了麻烦。为了做到这一点,我必须先使用New创建模块才能使用它:

要导入一个NPM模块,请按以下步骤操作:

1)安装browserify:

npm install ember-browserify --save-dev

2)安装您的模块:

npm install my-module --save-dev

3)将您的模块导入到您感兴趣的ember文件中(例如:app/controller/post.js):

import Module from 'npm:my-module';

4)通过使用New创建模块,在您的代码中使用该模块:

var output = new Module(var1, var2, etc.);


1

正如Pablo Morrasimplabs' post "Using npm libraries in Ember CLI"评论中所述,从Ember.js 2.15版本开始,第三方npm模块可以直接导入,无需使用插件或包装器:

https://www.emberjs.com/blog/2017/09/01/ember-2-15-released.html#toc_app-import-files-within-node_modules

很遗憾,文档仍在制作中,它并没有说明可以导入npm模块,只有bower和vendor模块:

https://github.com/emberjs/guides/issues/2017 https://guides.emberjs.com/v3.0.0/addons-and-dependencies/managing-dependencies/

我已经找到了两种方法,可以直接在Ember.js中导入第三方npm模块,这些方法来自于Ember CLI文档-关于管理依赖项。尽管该文档已经过时,并且指出只能导入bower和vendor的模块,而不能导入npm模块:

将npm模块作为标准匿名AMD资源

https://ember-cli.com/managing-dependencies#standard-anonymous-amd-asset

AMD:异步模块定义

我更喜欢并使用这种方式,因为它避免了全局变量,并遵循Ember.js的import约定。

ember-cli-build.js:

app.import('node_modules/ic-ajax/dist/amd/main.js', {
  using: [
    { transformation: 'amd', as: 'ic-ajax' }
  ]
});

"

amd是应用的转换类型,ic-ajax是在JavaScript文件中导入时要使用的模块名称。

在Ember.js的JavaScript文件(路由器、组件等)中:

"
import raw from 'ic-ajax';
// ...
icAjaxRaw( /* ... */ );

raw是由ic-ajax导出的一个模块。

这对我来说是可行的,尽管Ember CLI文档展示了另一种import方式,但对我不起作用,可能是因为我导入的特定包的原因:

import { raw as icAjaxRaw } from 'ic-ajax';
//...
icAjaxRaw( /* ... */ );

将npm模块作为全局变量

https://ember-cli.com/managing-dependencies#standard-non-amd-asset

ember-cli-build.js:

app.import('node_modules/moment/moment.js');

在Ember.js的JavaScript文件中(路由器、组件等):
/* global moment */
// No import for moment, it's a global called `moment`

// ...
var day = moment('Dec 25, 1995');

/* global moment */ 是用于 ESLint 的注释,用于在构建项目时不显示错误,因为文件中未定义 moment()

将 npm 模块作为标准命名的 AMD 资源

https://ember-cli.com/managing-dependencies#standard-named-amd-asset

Ember CLI还显示了第三个选项,但由于我导入的特定包可能不可行:

ember-cli-build.js:

app.import('node_modules/ic-ajax/dist/named-amd/main.js');

在Ember.js的JavaScript文件中(路由器,组件...):
import { raw as icAjaxRaw } from 'ic-ajax';
//...
icAjaxRaw( /* ... */ );

将npm模块作为AMD JavaScript模块

https://guides.emberjs.com/v3.0.0/addons-and-dependencies/managing-dependencies/#toc_amd-javascript-modules

我尝试按照Ember.js文档上关于依赖管理的方法进行操作,但是并没有奏效,可能是因为我导入的特定包有所不同:

ember-cli-build.js:

app.import('node_modules/ic-ajax/dist/named-amd/main.js', {
  exports: {
    'ic-ajax': [
      'default',
      'defineFixture',
      'lookupFixture',
      'raw',
      'request'
    ]
  }
});

在Ember.js的javascript文件中(路由,组件...):
import { raw as icAjaxRaw } from 'ic-ajax';
//...
icAjaxRaw( /* ... */ );

1
尽管这是一个旧的主题,但我仍想做出贡献,因为我花了很长时间来做这件事。我试图链接到Ember的特定包是“d3plus”,必须做各种各样的事情才能让它正常工作。
  1. npm install ember-browserify --save-dev
  2. npm install d3plus --save-dev
  3. ember install ember-cli-coffeescript
  4. npm install --save-dev coffeeify coffeescript

然后在您的组件中进行以下操作: import d3plus from 'npm:d3plus';

很长一段时间里,当它正在搜索coffescript时,我一直在收到运行时错误,并想到这对寻找d3plus的人会有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接