javascript 将 npm 模块编译成单个文件,无依赖
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22710887/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Compile an npm module into a single file, without dependencies
提问by Prajjwal
I'm trying to compile an the uncssnpm module into a single .js file that is suitable for compilation by ExecJS. For example, the coffee script guy has this. The goal is to create a simple ruby wrapper for it, similar to ruby-coffee-script.
我正在尝试将uncssnpm 模块编译成适合 ExecJS 编译的单个 .js 文件。例如,咖啡脚本家伙有这个. 目标是为它创建一个简单的 ruby 包装器,类似于ruby-coffee-script。
What I have tried to far:
我已经尝试过的:
- Came across an answer that suggested UglifyJS. Got nowhere with it.
Used browserify, which should have done the trick, but it fails to compile lib/uncss.js with the following error message:
Error: ENOENT, open 'tls' while resolving "tls" from file /home/prajjwal/code/uncss/node_modules/request/node_modules/forever-agent/index.js
- 遇到一个建议 UglifyJS 的答案。无处可去。
使用了 browserify,它应该可以解决问题,但它无法编译 lib/uncss.js,并显示以下错误消息:
Error: ENOENT, open 'tls' while resolving "tls" from file /home/prajjwal/code/uncss/node_modules/request/node_modules/forever-agent/index.js
I suppose this is because browserify does not have a proper shim for it? I'm also concerned about the shims that browserify replaces node modules with. Are they completely safe to use? I'm going to be embedding this into a ruby gem. Don't think browserify is what I should be using. Is there another way I can generate a stand alone .js from an npm module?
我想这是因为 browserify 没有合适的垫片吗?我还担心 browserify 替换节点模块的垫片。它们使用起来是否完全安全?我将把它嵌入到一个 ruby gem 中。不要认为 browserify 是我应该使用的。还有另一种方法可以从 npm 模块生成独立的 .js 吗?
Any help appreciated.
任何帮助表示赞赏。
采纳答案by voithos
Although it doesn't quite seem like it would be the right tool for the job, it appears that browserify is the closest thing to what you're looking for.
虽然它看起来不太适合这项工作,但看起来 browserify 是最接近您正在寻找的东西。
To be complete, here are the versions of the tools I used: Node v0.10.26
and browserify 3.38.0
. I didn't test with other version, so they may have problems.
为了完整起见,以下是我使用的工具的版本:Node v0.10.26
和browserify 3.38.0
. 我没有用其他版本测试,所以他们可能有问题。
Here are the steps that I took after cloning uncss
:
以下是我克隆后采取的步骤uncss
:
npm install
, which downloads and sets up the proper packagesDue to some sort of versioning problem with NPM, I had to manually install the
graceful-fs
package (a dependency of one ofuncss
's dependencies) from Github (it wasn't available vianpm
)npm install https://github.com/isaacs/node-graceful-fs/tarball/v2.0.3
At this point, I ran browserify. It turns out that browserify has a
--bare
flag, which does a couple of things:Alias for both --no-builtins, --no-commondir, and sets --insert-global-vars to just "__filename,__dirname". This is handy if you want to run bundles in node.
With this flag, browserify doesn't inject its own shims for core modules. The full command I used was:
browserify lib/uncss.js --bare > uncss.js
npm install
, 下载并设置正确的包由于 NPM 的某种版本控制问题,我不得不从 Github手动安装
graceful-fs
包(其中一个依赖项uncss
的依赖项)(无法通过npm
)npm install https://github.com/isaacs/node-graceful-fs/tarball/v2.0.3
此时,我运行了 browserify。事实证明, browserify 有一个
--bare
标志,它做了几件事:--no-builtins、--no-commondir 的别名,并将 --insert-global-vars 设置为“__filename,__dirname”。如果你想在 node.js 中运行包,这很方便。
使用此标志,browserify 不会为核心模块注入自己的垫片。我使用的完整命令是:
browserify lib/uncss.js --bare > uncss.js
After doing the above, the file uncss.js
contained uncss
along with its bundled dependencies. Unfortunately, since browserify wraps everything inside its own require
function, the now-bundled modules doesn't export anything initially.
完成上述操作后,该文件及其捆绑的依赖项uncss.js
包含uncss
在内。不幸的是,由于 browserify 将所有内容都封装在其自己的require
函数中,因此现在捆绑的模块最初不会导出任何内容。
$ node
> require('./uncss')
{}
>
To fix this, I had to change the initial line of the generated bundle from this:
为了解决这个问题,我必须从这个更改生成的包的初始行:
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
to this:
对此:
module.exports = (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require,ex;for(var o=0;o<r.length;o++)ex=s(r[o]);return ex})({1:[function(require,module,exports){
Note: it's notjust the module.exports
addition - there's some modification in the middle that was needed also*.
注:这是不是只是module.exports
增加-有在还需要*中间的一些修改。
After that, the bundle seemed to work:
在那之后,捆绑似乎工作:
$ node
> require('./uncss')
[Function: init]
>
*: Essentially, browserify defines an inner function s(o, u)
that acts like require
. The surrounding code starts off by looping through what looks like a list of "main modules" (in this case, there's just one), require
ing them, but not storing the result. It then returns s
, the require
-like function (why, I'm not sure) as the output of the entire anonymous function. All I had to do was add a variable to store the results, and then return
that instead.
*:本质上,browserify 定义了一个function s(o, u)
像require
. 周围的代码首先循环遍历“主模块”列表(在这种情况下,只有一个),require
对它们进行循环,但不存储结果。然后它返回s
,require
类似函数(为什么,我不确定)作为整个匿名函数的输出。我所要做的就是添加一个变量来存储结果,然后return
改为。
回答by xer0x
Browserify has a --standalone flag that can help here.
Browserify 有一个 --standalone 标志,可以在这里提供帮助。
On the command line:
在命令行上:
browserify -s moduleName --bare moduleName.js -o filename.js
In your node script you can import the concatenated module normally:
在您的节点脚本中,您可以正常导入串联模块:
var moduleName = require('./filename');
However, you will may still need to ignore and/or stub out any tricky modules.
但是,您可能仍然需要忽略和/或剔除任何棘手的模块。
回答by Rodrigo Polo
While it is not impossible, it is a bit complicated, there is no tool that I know to do it automatically, but it coulb be done manually.
虽然不是不可能,但有点复杂,我知道没有工具可以自动完成,但可以手动完成。
So, if you load a module in this way:
因此,如果您以这种方式加载模块:
var async = require('async');
You can include the source of that module, first, declaring the module instance in your main script:
您可以包含该模块的源代码,首先在主脚本中声明模块实例:
var global_async = null;
Then, include the module code inside an anonymous function and replace the "module.exports" with the global var you declared before:
然后,将模块代码包含在匿名函数中,并将“module.exports”替换为您之前声明的全局变量:
module.exports = async
With
和
global_async = async;
Problem is that there are a lot of dependencies for "uncss", each one with some dependencies, so it is to much work to be done, but not impossible... but at the end, this module also requires some external binaries like "phantomjs".
问题是“uncss”有很多依赖项,每个依赖项都有一些依赖项,所以要做的工作很多,但并非不可能……但最后,这个模块还需要一些外部二进制文件,例如“幻象”。
If you want to build a gem that create a wrapper around "uncss" you can check if node and uncss are installed before anything, if not, install both, and then just call them, just like uncss does with phantomjs.
如果您想构建一个围绕“uncss”创建包装器的 gem,您可以在任何事情之前检查 node 和 uncss 是否已安装,如果没有,则安装两者,然后调用它们,就像 uncss 对 phantomjs 所做的那样。