Javascript 如何通过npm将自定义库导入Ember
尽管关于它的博客文章似乎太多了,但我仍然在努力通过npm将自定义库作为我的余烬应用程序的依赖项 我已经编写了一个WebGL库,目前已通过npm从私有存储库将其导入我的Ember应用程序。这项工作目前正在进行,并且正在生产中,但工作流程有些笨拙。该库是使用NodeJS模块(require->export.modules)编写的。目前我只是在我的src文件上使用babel,这会导致生成一个文件夹,其中ES5版本的文件仍然是分开的 然后我有一个如下所示的索引文件:Javascript 如何通过npm将自定义库导入Ember,javascript,ember.js,npm,ecmascript-6,Javascript,Ember.js,Npm,Ecmascript 6,尽管关于它的博客文章似乎太多了,但我仍然在努力通过npm将自定义库作为我的余烬应用程序的依赖项 我已经编写了一个WebGL库,目前已通过npm从私有存储库将其导入我的Ember应用程序。这项工作目前正在进行,并且正在生产中,但工作流程有些笨拙。该库是使用NodeJS模块(require->export.modules)编写的。目前我只是在我的src文件上使用babel,这会导致生成一个文件夹,其中ES5版本的文件仍然是分开的 然后我有一个如下所示的索引文件: var Helper = requi
var Helper = require('./com/XXXX/utils/Helper');
module.exports = {
Module1: require('./com/XXXX/media/Module1'),
Module2: require('./com/XXXX/media/Module2'),
Module3: require("./com/XXXX/media/Module3"),
Module4: require('./Module4'),
Module5: require('./com/XXXX/media/Module5'),
Module6: Helper.Module6,
Module7: Helper.Module7
};
class Module5 {
//Magic rendering code
}
module.exports = Module5;
export default class Module5 {
//Magic rendering code
}
(function() {
function mediaVendorModule(moduleName) {
'use strict';
var MyModule = self['ModuleNamespace']; // Global
return function() {
return {
'default': MyModule[moduleName]
};
};
}
function helperVendorModule() {
'use strict';
var MyModule = self['ModuleNamespace']; // Global
return {
Module6: MyModule.helper.Module6,
Module7: MyModule.helper.Module7
};
}
define('com/XXXX/media/Module4', [], mediaVendorModule('Module4'));
define('com/XXXX/media/Module1', [], mediaVendorModule('Module1'));
define('com/XXXX/media/Module2', [], mediaVendorModule('Module2'));
define('com/XXXX/media/Module3', [], mediaVendorModule('Module3'));
define('com/XXXX/media/Module5', [], mediaVendorModule('Module5'));
define('com/XXXX/Helper', [], helperVendorModule);
})();
使用npm,我可以将此构建目录安装到我的Ember应用程序中,并使用以下语法导入我需要的模块:
import webglRenderLibrary from 'npm:webglRenderLibrary';
const { Module5 } = webglRenderLibrary;
其中Module5是库中的一个类,导出方式如下:
var Helper = require('./com/XXXX/utils/Helper');
module.exports = {
Module1: require('./com/XXXX/media/Module1'),
Module2: require('./com/XXXX/media/Module2'),
Module3: require("./com/XXXX/media/Module3"),
Module4: require('./Module4'),
Module5: require('./com/XXXX/media/Module5'),
Module6: Helper.Module6,
Module7: Helper.Module7
};
class Module5 {
//Magic rendering code
}
module.exports = Module5;
export default class Module5 {
//Magic rendering code
}
(function() {
function mediaVendorModule(moduleName) {
'use strict';
var MyModule = self['ModuleNamespace']; // Global
return function() {
return {
'default': MyModule[moduleName]
};
};
}
function helperVendorModule() {
'use strict';
var MyModule = self['ModuleNamespace']; // Global
return {
Module6: MyModule.helper.Module6,
Module7: MyModule.helper.Module7
};
}
define('com/XXXX/media/Module4', [], mediaVendorModule('Module4'));
define('com/XXXX/media/Module1', [], mediaVendorModule('Module1'));
define('com/XXXX/media/Module2', [], mediaVendorModule('Module2'));
define('com/XXXX/media/Module3', [], mediaVendorModule('Module3'));
define('com/XXXX/media/Module5', [], mediaVendorModule('Module5'));
define('com/XXXX/Helper', [], helperVendorModule);
})();
我不必安装任何其他插件,也不必将库文件导入ember供应商文件,因为很多博客帖子都说,为了让它正常工作,你必须这样做。我真的不明白为什么这个方法有效,但它确实有效
“”\_(ツ)_/“”
我从来没有真正喜欢过这个设置/工作流程(也不知道它为什么会工作),所以我正在尝试改进它,但是我在Ember、JS模块等方面的许多知识差距让它变得很困难
我想做的第一件事是将库移到ES6模块(导入->导出).据我所知,ES6模块更加精简,而且是未来的发展趋势,因此我更愿意在我的库中使用它们。更改所有源代码有点耗费人力,但效果很好,使我能够为我的库开发创建一个良好的工作流程
模块5现在看起来像这样:
var Helper = require('./com/XXXX/utils/Helper');
module.exports = {
Module1: require('./com/XXXX/media/Module1'),
Module2: require('./com/XXXX/media/Module2'),
Module3: require("./com/XXXX/media/Module3"),
Module4: require('./Module4'),
Module5: require('./com/XXXX/media/Module5'),
Module6: Helper.Module6,
Module7: Helper.Module7
};
class Module5 {
//Magic rendering code
}
module.exports = Module5;
export default class Module5 {
//Magic rendering code
}
(function() {
function mediaVendorModule(moduleName) {
'use strict';
var MyModule = self['ModuleNamespace']; // Global
return function() {
return {
'default': MyModule[moduleName]
};
};
}
function helperVendorModule() {
'use strict';
var MyModule = self['ModuleNamespace']; // Global
return {
Module6: MyModule.helper.Module6,
Module7: MyModule.helper.Module7
};
}
define('com/XXXX/media/Module4', [], mediaVendorModule('Module4'));
define('com/XXXX/media/Module1', [], mediaVendorModule('Module1'));
define('com/XXXX/media/Module2', [], mediaVendorModule('Module2'));
define('com/XXXX/media/Module3', [], mediaVendorModule('Module3'));
define('com/XXXX/media/Module5', [], mediaVendorModule('Module5'));
define('com/XXXX/Helper', [], helperVendorModule);
})();
在库的package.json
中,我有许多npm脚本正在调用watchify,因此我可以在演示文件中单独测试我的模块
{
"name": "webglRenderLibrary",
"main": "dist/js/app.js",
"version": "2.0.5",
"author": "JibJab Media",
"description": "WebGL Render Library",
"repository": "private.git",
"scripts": {
"watch-sass": "sass --watch src/scss/app.scss:demo/css/app.css",
"watch-js": "watchify src/js/index.js -t babelify -o dist/js/app.js -dv",
"watch-module1": "watchify src/js/demos/Module1Demo.js -t babelify -o demo/js/Module1Demo.js -dv",
"watch-module2": "watchify src/js/demos/Module2Demo.js -t babelify -o demo/js/Module2Demo.js -dv",
"watch-module3": "watchify src/js/demos/Module3Demo.js -t babelify -o demo/js/Module3Demo.js -dv",
"watch-module4": "watchify src/js/demos/Module4Demo.js -t babelify -o demo/js/Module4Demo.js -dv",
"watch-module5": "watchify src/js/demos/Module5Demo.js -t babelify -o demo/js/Module5Demo.js -dv",
"watch-module6": "watchify src/js/demos/Module6Demo.js -t babelify -o demo/js/Module6Demo.js -dv",
"watch": "npm run watch-sass & npm run watch-module1 & npm run watch-module2 & npm run watch-module3 & npm run watch-module5 & npm run watch-module5 & npm run watch-module6",
"build-sass": "sass src/scss/app.scss:dist/css/app.css --style compressed",
"build-js": "browserify src/js/index.js -t [ babelify --presets [ \"env\" ] ] | uglifyjs -mc > dist/js/app.js",
"build": "npm run build-js & npm run build-sass",
"test": "mocha --require babel-core/register",
"test-coverage": "nyc mocha --require babel-core/register"
},
"browserify": {
"transform": [
"babelify"
]
},
"dependencies": {
"babel-preset-env": "1.6.1",
"babelify": "^7.2.0",
"opentype.js": "0.8.0"
},
"devDependencies": {
"babel-cli": "*",
"mocha": "5.0.5",
"nyc": "11.6.0",
"watchify": "3.11.0"
},
"bugs": {
"url": "private/issues"
},
"homepage": "private#readme",
"private": true
}
我提出这一切都是为了指出,我对ES6模块的转换进展顺利。我为各个模块编写的测试Js文件编译得很好,可以在测试HTML文件中运行它们,WebGL可以正确呈现
现在,这里是我的知识变得模糊的地方
该库包含7个我想公开的模块,以便Ember应用程序可以使用它们。因此,我在库中有一个index.js
文件,它只需导入每个模块,然后导出它们。(如果不是这样做的话,请告诉我)
据我所知,这使我能够让browserify/babelify将我的ES6模块库转换成Ember可以使用的东西。在库package.json
中,我有一个“构建”脚本,它运行browserify、babel和uglify,将我的整个库压缩成dist/js/app.js
中的一个小型文件,这是入口点t位于库package.json
中的main下
我在想,这应该是目前在我的余烬应用程序中运行的同一个代码。唯一的区别应该是它已被browseridy放入一个文件中,并用Uglify缩小(如果我错了,请纠正我,我认为我错了).我原以为我不必对我的Ember应用程序进行任何更改,但现在我得到了:
Uncaught TypeError: Module5 is not a constructor
以我以前的方式导入时:
import webglRenderLibrary from 'npm:webglRenderLibrary';
const { Module5 } = webglRenderLibrary;
所有这些都让我产生了几个问题:
lodash
)package.json
中,我添加了“standalone”参数,它神奇地工作了
"build-js": "browserify --standalone WebGLRenderLibrary src/js/index.js -t [ babelify --presets [ \"env\" ] ] | uglifyjs -mc > dist/js/app.js",
我不知道它在幕后做了什么,但现在它正在发挥作用。希望很快会有更好的解决方案出现。更新:是一个干净的、小的、社区认可的插件,允许NPM模块导入到Ember中,而无需设置、样板文件或增加认知负载。请先使用它。仅在极端情况下使用(遗留代码/不兼容用法)您需要以下手动工作
如果没有和你一起经历同样的情况,我觉得回答你的问题只是一种猜测。因为我不想错过代表,我将尝试描述我如何完成同样的情况 首先,在应用程序中包含供应商代码与在加载项中包含供应商代码之间存在细微差异。我的经验是基于创建一个ember加载项。然而,由于应用程序允许在repo加载项中使用加载项,因此加载项的过程可以很容易地在实际应用程序中复制。我还建议单独执行此操作(作为一个单独的插件或回购插件)比作为应用程序本身的一部分更有益 第一个障碍是确保您希望使用的模块与浏览器兼容,因为实际模块将在浏览器中使用。如果您希望使用的NPM模块是特定于节点的,则