使用浏览器化的 JS 库 Angular 2
Using a browserified JS library with Angular 2
我想在我的 Angular 2 项目中使用 libquassel (https://github.com/magne4000/node-libquassel)。该库是浏览器化的,所以理论上它应该可以工作,但我不确定如何将它导入我的项目。
我尝试添加到我的 typings.d.ts
declare module 'libquassel';
然后使用
导入库
import * as Quassel from 'libquassel';
但我得到
EXCEPTION: net.Socket is not a function
当我尝试 运行 我的代码时,我认为这是另一个嵌入 client/libquassel.js
文件的 browserify 库。
如何使用这个库?
编辑:我会在这里回答所有问题:
- 我的设置是一个普通的 angular-cli 项目。没有花哨的东西,只是
ng new proj1
然后是 npm install libquassel --save
.
- 我的
index.html
没有任何其他 ng new
没有放在那里的东西。
- 我尝试使用
import * as Quassel from 'libquassel'
和 var Quassel = require('quassel')
(以及它们的排列)导入库,但没有任何运气(错误从 unknown function 'require'
到 can't find module lib|quassel
)。
重现我的项目的步骤:
ng new test
cd test
npm install libquassel --save
ng g s quassel
然后将QuasselService
添加到app.module.ts
中的providers
数组。
这将是我的问题的一个很好的演示,即如何在我的 QuasselService
.
中导入 libquassel
Angular-cli使用webpack
您需要将 JS 文件添加到 angular-cli.json 文件中的 apps[0].scripts 中,然后 WebPack 会像加载标签一样进行捆绑。
apps:[
{
...
"scripts": [
"../node_modules/libquassel/client/libquassel.js"
],
如果这样做,您可以通过在 src/typings.d.ts 或组件中添加 declare var Quassel :any;
来实现。
let quassel = new Quassel("localhost", 4242, {}, function(next) {
next("user", "password");
});
quassel.connect();
更新(修复它,这次是真的)
它在您的代码中不起作用有一个很好的理由:因为我对您撒了谎。如果您还没有 "diffed" ,那么这是我真正的作弊方法。
我仍然需要 require
libquassel 2 次,但第一次不是通过调用 require
完成的,这是无用的,而是通过将它添加到 angular-cli.json
到 scripts
部分:
"scripts": [
"../node_modules/libquassel/client/libquassel.js"
],
这很重要,因为 "client/libquassel.js" 声明了它自己的 require
但没有明确导出它,所以如果您这样做
require('libquassel/client/libquassel.js');
libquassel 的自定义 require
卡在匿名命名空间中,您无法访问它。另一方面,将它添加到 scripts
部分,让 libquassel.js 用它的 require
污染全局命名空间(即 window
),从而使其工作。
因此,使其工作的实际步骤是:
- 将 client/libquassel.js 添加到
angular-cli.json
的脚本 section
- 使用额外的
require
实际加载 Quassel
模块
let Quassel = window['require']('quassel'); // note that usingg require('quassel') leads to compilation error
let quasselObj = new Quassel(...);
这是我的尝试。看起来你需要 require
"quassel" 2 次:第一次从 "../node_modules/libquassel/client/libquassel.js" 加载 JS,第二次到让来自那个 JS 的覆盖 require
实际上解析 "quassel"。在 'main.ts':
中,这是一个似乎对我有用的技巧
require('../node_modules/libquassel/client/libquassel.js');
let Quassel = window['require']('quassel'); // note that using require('quassel') leads to compilation error
let quasselObj = new Quassel(...);
我还需要一个技巧来避免因编译错误而失败:特别是我必须使用 window['require']
而不是仅 require
进行第二次调用,因为它是对内部 [= client/libquassel.js
中定义的 16=] 和 Node/Angular-cli 单独无法处理它。
请注意,在该设置之后,我的应用程序仍然因某些 AJAX 中的运行时错误而失败,因为浏览 libquassel.js
似乎需要在服务器端 URL 处设置代理像 /api/vm/net/connect
,这可能是 net-browsify 的服务器端应该做的,但我没有尝试设置它。
回复评论
看起来您使用的是旧版本的 Angular-CLI,如果您升级,一切都应该可以正常工作。
这是 ng --version
在我原来的机器上告诉我的
angular-cli: 1.0.0-beta.28.3
node: 6.10.0
os: win32 x64
@angular/common: 2.4.10
@angular/compiler: 2.4.10
@angular/core: 2.4.10
@angular/forms: 2.4.10
@angular/http: 2.4.10
@angular/platform-browser: 2.4.10
@angular/platform-browser-dynamic: 2.4.10
@angular/router: 3.4.10
@angular/compiler-cli: 2.4.10
当我试图将我的原始项目复制到另一台机器时,我也遇到了关于 require
的编译错误,但是当我将 Angular-CLI 更新为
时
@angular/cli: 1.0.0
node: 6.10.0
os: darwin x64
@angular/common: 2.4.10
@angular/compiler: 2.4.10
@angular/core: 2.4.10
@angular/forms: 2.4.10
@angular/http: 2.4.10
@angular/platform-browser: 2.4.10
@angular/platform-browser-dynamic: 2.4.10
@angular/router: 3.4.10
@angular/cli: 1.0.0
@angular/compiler-cli: 2.4.10
它编译和工作相同。我所做的只是按照说明
The package "angular-cli" has been deprecated and renamed to "@angular/cli".
Please take the following steps to avoid issues:
"npm uninstall --save-dev angular-cli"
"npm install --save-dev @angular/cli@latest"
然后按照 ng serve
的说明更新了 angular-cli.json
工作起来很有魅力:
declare var require;
const Quassel = require( 'libquassel/lib/libquassel.js' );
console.log( 'Quassel', Quassel );
查看node_module中libquassel
的文件夹,发现根目录下没有index.js
。
当没有 index.js
时,你不能 这样做:
require( 'libquassel' );
仅仅是因为 node 不知道要为您提供什么,所以您需要指定确切的路径,在这种情况下这还不错。
此外,请注意,最好将 declare var require;
移动到位于 src 文件夹下的 typings 文件,因为您可能需要再次声明它,所以最好放在那儿。
编辑:
这是我在尝试像下面这样实例化 Quassel 之后发现的:
const Quassel = require( 'libquassel/lib/libquassel.js' );
console.log( 'Quassel', Quassel );
var quassel = new Quassel( "quassel.domain.tld",
4242,
{ backloglimit : 10 },
function ( next ) {
next( "user", "password" );
} );
console.log( 'quassel', quassel );
这是我的控制台日志:
但是话虽如此,我意识到 libquassel.js 内部存在问题,如下所示:
在第 10 行,他们这样做:
var net = require('net');
看看他们的 package.json,没有 net
这样的东西,有 net-browserify-alt
;
因此,如果他们将该导入更改为:
var net = require('net-browserify-alt'),
一切正常。
话虽如此,显然你不想编辑你的 node_module,但我真的很惊讶这甚至在 angular 和 webpack 之外是如何工作的,因为很明显他们'我提到了一个错误的 node_module 如果你 google ,只有一个名为 net
的包,我看了一下它是空的和虚拟的 !!!!
** ********** 更新:********* **
具体需要做什么:
1- 运行 ng eject
这将在您的根目录中生成一个 webpack.conf.js
。
2- 在里面找到 resolve
属性 并添加:
"alias":{
'net':'net-browserify-alt'
},
所以你的决心可能看起来像:
"resolve": {
"extensions": [
".ts",
".js"
],
"alias":{
'net':'net-browserify-alt'
},
"modules": [
"./node_modules"
]
},
3- 导入并使用它:
declare var require;
const Quassel = require( 'libquassel/lib/libquassel.js' );
console.log( 'Quassel', Quassel );
var quassel = new Quassel( "quassel.domain.tld",
4242,
{ backloglimit : 10 },
function ( next ) {
next( "user", "password" );
} );
console.log( 'quassel', quassel );
注意:
查看 webpack 配置,似乎 webpack 喜欢覆盖几个模块:
"node": {
"fs": "empty",
"global": true,
"crypto": "empty",
"tls": "empty",
"net": "empty",
"process": true,
"module": false,
"clearImmediate": false,
"setImmediate": false
}
我不完全知道为什么,但这个列表在 webpack 配置中,似乎使 net
变得不安全(空),这就是我们必须创建别名的原因。
关键问题是浏览器化 libquassel
库中包含一个全局 require
函数。这与标准 require
函数冲突。
有很多方法可以处理这个问题,但一种解决方案是将 /libquassel/client/libquassel.js
(和缩小版本)复制到您的 /src/app/
目录。
然后 运行 在这些文件中进行搜索和替换,将所有出现的 require
更改为 _quasselRequire_
您可以为 libquassel.js
和 libquassel.min.js
执行此操作。
要利用它,您可以在 quassel.service.ts
:
中执行类似的操作
import { Injectable } from '@angular/core';
import * as dummyQuassel1 from './libquassel.js'
var dummyQuassel2 = dummyQuassel1; // something just to force the import
declare var _quasselRequire_ :any;
@Injectable()
export class QuasselService {
constructor() {
// set up in the constructor as a demo
let Quassel = _quasselRequire_( 'quassel' );
console.log('Quassel', Quassel);
var quassel = new Quassel(
"quassel.domain.tld",
4242,
{ backloglimit : 10 },
function ( next ) {
next( "user", "password" );
}
);
console.log('quassel', quassel);
quassel.on('network.init', function(networkId) {
console.log("before net");
var network = quassel.getNetworks().get(networkId);
console.log("after net");
// ...
});
console.log("before connect");
quassel.connect();
console.log("after connect");
}
getQuassel() {
return 'My Quassel service';
}
}
这本身会导致错误:
POST http://localhost:4200/api/vm/net/connect 404 (Not Found)
和
Error: Uncaught, unspecified 'error' event.
at new Error (native)
at Quassel.n.emit (http://localhost:4200/main.bundle.js:570:4210) [angular]
at Socket. (http://localhost:4200/main.bundle.js:810:19931) [angular]
at Socket.EventEmitter.emit (http://localhost:4200/main.bundle.js:573:1079) [angular] ...
但据我所知,这是相当正常的,因为我还没有设置 Express 等。
注意:名称 _quasselRequire_
可以是任何适合您的名称。
我想在我的 Angular 2 项目中使用 libquassel (https://github.com/magne4000/node-libquassel)。该库是浏览器化的,所以理论上它应该可以工作,但我不确定如何将它导入我的项目。
我尝试添加到我的 typings.d.ts
declare module 'libquassel';
然后使用
导入库import * as Quassel from 'libquassel';
但我得到
EXCEPTION: net.Socket is not a function
当我尝试 运行 我的代码时,我认为这是另一个嵌入 client/libquassel.js
文件的 browserify 库。
如何使用这个库?
编辑:我会在这里回答所有问题:
- 我的设置是一个普通的 angular-cli 项目。没有花哨的东西,只是
ng new proj1
然后是npm install libquassel --save
. - 我的
index.html
没有任何其他ng new
没有放在那里的东西。 - 我尝试使用
import * as Quassel from 'libquassel'
和var Quassel = require('quassel')
(以及它们的排列)导入库,但没有任何运气(错误从unknown function 'require'
到can't find module lib|quassel
)。 重现我的项目的步骤:
ng new test cd test npm install libquassel --save ng g s quassel
然后将QuasselService
添加到app.module.ts
中的providers
数组。
这将是我的问题的一个很好的演示,即如何在我的 QuasselService
.
libquassel
Angular-cli使用webpack
您需要将 JS 文件添加到 angular-cli.json 文件中的 apps[0].scripts 中,然后 WebPack 会像加载标签一样进行捆绑。
apps:[
{
...
"scripts": [
"../node_modules/libquassel/client/libquassel.js"
],
如果这样做,您可以通过在 src/typings.d.ts 或组件中添加 declare var Quassel :any;
来实现。
let quassel = new Quassel("localhost", 4242, {}, function(next) {
next("user", "password");
});
quassel.connect();
更新(修复它,这次是真的)
它在您的代码中不起作用有一个很好的理由:因为我对您撒了谎。如果您还没有 "diffed" ,那么这是我真正的作弊方法。
我仍然需要 require
libquassel 2 次,但第一次不是通过调用 require
完成的,这是无用的,而是通过将它添加到 angular-cli.json
到 scripts
部分:
"scripts": [
"../node_modules/libquassel/client/libquassel.js"
],
这很重要,因为 "client/libquassel.js" 声明了它自己的 require
但没有明确导出它,所以如果您这样做
require('libquassel/client/libquassel.js');
libquassel 的自定义 require
卡在匿名命名空间中,您无法访问它。另一方面,将它添加到 scripts
部分,让 libquassel.js 用它的 require
污染全局命名空间(即 window
),从而使其工作。
因此,使其工作的实际步骤是:
- 将 client/libquassel.js 添加到
angular-cli.json
的脚本 - 使用额外的
require
实际加载Quassel
模块
section
let Quassel = window['require']('quassel'); // note that usingg require('quassel') leads to compilation error
let quasselObj = new Quassel(...);
这是我的尝试。看起来你需要 require
"quassel" 2 次:第一次从 "../node_modules/libquassel/client/libquassel.js" 加载 JS,第二次到让来自那个 JS 的覆盖 require
实际上解析 "quassel"。在 'main.ts':
require('../node_modules/libquassel/client/libquassel.js');
let Quassel = window['require']('quassel'); // note that using require('quassel') leads to compilation error
let quasselObj = new Quassel(...);
我还需要一个技巧来避免因编译错误而失败:特别是我必须使用 window['require']
而不是仅 require
进行第二次调用,因为它是对内部 [= client/libquassel.js
中定义的 16=] 和 Node/Angular-cli 单独无法处理它。
请注意,在该设置之后,我的应用程序仍然因某些 AJAX 中的运行时错误而失败,因为浏览 libquassel.js
似乎需要在服务器端 URL 处设置代理像 /api/vm/net/connect
,这可能是 net-browsify 的服务器端应该做的,但我没有尝试设置它。
回复评论
看起来您使用的是旧版本的 Angular-CLI,如果您升级,一切都应该可以正常工作。
这是 ng --version
在我原来的机器上告诉我的
angular-cli: 1.0.0-beta.28.3
node: 6.10.0
os: win32 x64
@angular/common: 2.4.10
@angular/compiler: 2.4.10
@angular/core: 2.4.10
@angular/forms: 2.4.10
@angular/http: 2.4.10
@angular/platform-browser: 2.4.10
@angular/platform-browser-dynamic: 2.4.10
@angular/router: 3.4.10
@angular/compiler-cli: 2.4.10
当我试图将我的原始项目复制到另一台机器时,我也遇到了关于 require
的编译错误,但是当我将 Angular-CLI 更新为
@angular/cli: 1.0.0
node: 6.10.0
os: darwin x64
@angular/common: 2.4.10
@angular/compiler: 2.4.10
@angular/core: 2.4.10
@angular/forms: 2.4.10
@angular/http: 2.4.10
@angular/platform-browser: 2.4.10
@angular/platform-browser-dynamic: 2.4.10
@angular/router: 3.4.10
@angular/cli: 1.0.0
@angular/compiler-cli: 2.4.10
它编译和工作相同。我所做的只是按照说明
The package "angular-cli" has been deprecated and renamed to "@angular/cli".
Please take the following steps to avoid issues:
"npm uninstall --save-dev angular-cli"
"npm install --save-dev @angular/cli@latest"
然后按照 ng serve
angular-cli.json
工作起来很有魅力:
declare var require;
const Quassel = require( 'libquassel/lib/libquassel.js' );
console.log( 'Quassel', Quassel );
查看node_module中libquassel
的文件夹,发现根目录下没有index.js
。
当没有 index.js
时,你不能 这样做:
require( 'libquassel' );
仅仅是因为 node 不知道要为您提供什么,所以您需要指定确切的路径,在这种情况下这还不错。
此外,请注意,最好将 declare var require;
移动到位于 src 文件夹下的 typings 文件,因为您可能需要再次声明它,所以最好放在那儿。
编辑: 这是我在尝试像下面这样实例化 Quassel 之后发现的:
const Quassel = require( 'libquassel/lib/libquassel.js' );
console.log( 'Quassel', Quassel );
var quassel = new Quassel( "quassel.domain.tld",
4242,
{ backloglimit : 10 },
function ( next ) {
next( "user", "password" );
} );
console.log( 'quassel', quassel );
这是我的控制台日志:
在第 10 行,他们这样做:
var net = require('net');
看看他们的 package.json,没有 net
这样的东西,有 net-browserify-alt
;
因此,如果他们将该导入更改为:
var net = require('net-browserify-alt'),
一切正常。
话虽如此,显然你不想编辑你的 node_module,但我真的很惊讶这甚至在 angular 和 webpack 之外是如何工作的,因为很明显他们'我提到了一个错误的 node_module 如果你 google ,只有一个名为 net
的包,我看了一下它是空的和虚拟的 !!!!
** ********** 更新:********* **
具体需要做什么:
1- 运行 ng eject
这将在您的根目录中生成一个 webpack.conf.js
。
2- 在里面找到 resolve
属性 并添加:
"alias":{
'net':'net-browserify-alt'
},
所以你的决心可能看起来像:
"resolve": {
"extensions": [
".ts",
".js"
],
"alias":{
'net':'net-browserify-alt'
},
"modules": [
"./node_modules"
]
},
3- 导入并使用它:
declare var require;
const Quassel = require( 'libquassel/lib/libquassel.js' );
console.log( 'Quassel', Quassel );
var quassel = new Quassel( "quassel.domain.tld",
4242,
{ backloglimit : 10 },
function ( next ) {
next( "user", "password" );
} );
console.log( 'quassel', quassel );
注意:
查看 webpack 配置,似乎 webpack 喜欢覆盖几个模块:
"node": {
"fs": "empty",
"global": true,
"crypto": "empty",
"tls": "empty",
"net": "empty",
"process": true,
"module": false,
"clearImmediate": false,
"setImmediate": false
}
我不完全知道为什么,但这个列表在 webpack 配置中,似乎使 net
变得不安全(空),这就是我们必须创建别名的原因。
关键问题是浏览器化 libquassel
库中包含一个全局 require
函数。这与标准 require
函数冲突。
有很多方法可以处理这个问题,但一种解决方案是将 /libquassel/client/libquassel.js
(和缩小版本)复制到您的 /src/app/
目录。
然后 运行 在这些文件中进行搜索和替换,将所有出现的 require
更改为 _quasselRequire_
您可以为 libquassel.js
和 libquassel.min.js
执行此操作。
要利用它,您可以在 quassel.service.ts
:
import { Injectable } from '@angular/core';
import * as dummyQuassel1 from './libquassel.js'
var dummyQuassel2 = dummyQuassel1; // something just to force the import
declare var _quasselRequire_ :any;
@Injectable()
export class QuasselService {
constructor() {
// set up in the constructor as a demo
let Quassel = _quasselRequire_( 'quassel' );
console.log('Quassel', Quassel);
var quassel = new Quassel(
"quassel.domain.tld",
4242,
{ backloglimit : 10 },
function ( next ) {
next( "user", "password" );
}
);
console.log('quassel', quassel);
quassel.on('network.init', function(networkId) {
console.log("before net");
var network = quassel.getNetworks().get(networkId);
console.log("after net");
// ...
});
console.log("before connect");
quassel.connect();
console.log("after connect");
}
getQuassel() {
return 'My Quassel service';
}
}
这本身会导致错误:
POST http://localhost:4200/api/vm/net/connect 404 (Not Found)
和
Error: Uncaught, unspecified 'error' event. at new Error (native) at Quassel.n.emit (http://localhost:4200/main.bundle.js:570:4210) [angular] at Socket. (http://localhost:4200/main.bundle.js:810:19931) [angular] at Socket.EventEmitter.emit (http://localhost:4200/main.bundle.js:573:1079) [angular] ...
但据我所知,这是相当正常的,因为我还没有设置 Express 等。
注意:名称 _quasselRequire_
可以是任何适合您的名称。