如何使用 Node.js 和 npm 自动压缩文件
How to automatically zip files with Node.js and npm
有没有办法在构建时使用 Node.js 和 npm 自动压缩某些文件?
例如,我有一个项目,该文件结构如下所示:
Project/
--lib/
--node_modules/
--test/
--index.js
--package.json
我希望能够将 lib 文件夹、node_modules 和 index.js 中的某些模块压缩到某个 zip 存档中,以便将其上传到 AWS Lambda,例如。我不需要压缩测试文件夹或测试 Node.js 模块(mocha 和 chai)。我什至创建了一个 bash 脚本来生成 zip 文件,但是有没有办法在调用 'npm install' 时自动执行这个脚本?
这应该是一个标准问题,应该有一个标准的解决方案,但我找不到。
更新
感谢迈克尔,决定使用 gulp。这是我的脚本,以防其他人在 AWS Lambda 中需要它:
var gulp = require('gulp');
var clean = require('gulp-clean');
var zip = require('gulp-zip');
var merge = require('merge-stream');
gulp.task('clean', function () {
var build = gulp.src('build', {read: false})
.pipe(clean());
var dist = gulp.src('dist', {read: false})
.pipe(clean());
return merge(build, dist);
});
gulp.task('build', function() {
var index = gulp.src('index.js')
.pipe(gulp.dest('build'));
var lib = gulp.src('lib/**')
.pipe(gulp.dest('build/lib'));
var async = gulp.src('node_modules/async/**')
.pipe(gulp.dest('build/node_modules/async'));
var collections = gulp.src('node_modules/collections/**')
.pipe(gulp.dest('build/node_modules/collections'));
var underscore = gulp.src('node_modules/underscore/**')
.pipe(gulp.dest('build/node_modules/underscore'));
var util = gulp.src('node_modules/util/**')
.pipe(gulp.dest('build/node_modules/util'));
var xml2js = gulp.src('node_modules/xml2js/**')
.pipe(gulp.dest('build/node_modules/xml2js'));
return merge(index, lib, async, collections, underscore, util, xml2js);
});
gulp.task('zip', ['build'], function() {
return gulp.src('build/*')
.pipe(zip('archive.zip'))
.pipe(gulp.dest('dist'));
});
gulp.task('default', ['zip']);
你应该看看npm scripts。
您的存储库中仍然需要一个 bash 脚本,但它会在某些 npm
任务执行时自动触发。
我会使用 gulp 使用 gulp-sftp、gulp-tar 和 gulp-gzip 以及别名作为命令。在您的用户主文件夹中创建一个名为 .bash_aliases
的文件,其中包含
alias installAndUpload='npm install && gulp runUploader'
重新启动后,您可以使用此别名同时调用这两个操作。
gulp 文件可能看起来像这样
var gulp = require('gulp');
var watch = require('gulp-watch');
var sftp = require('gulp-sftp');
var gzip = require('gulp-gzip');
gulp.task('runUploader', function () {
gulp.src('.path/to/folder/to/compress/**')
.pipe(tar('archive.tar'))
.pipe(gzip())
.pipe(gulp.dest('path/to/folder/to/store')) // if you want a local copy
.pipe(sftp({
host: 'website.com',
user: 'johndoe',
pass: '1234'
}))
});
当然你也可以加上gulp-watch 自动创建tar/zip目录有变化就上传
如果您需要自动执行任务,请查看 Grunt or Gulp。
Grunt 需要的插件:
在 https://gist.github.com/ctulek/6f16352ebdfc166ce905
查看我的要点
除了最初创建 lambda 函数(它只更新代码)之外,这对您提到的所有任务都使用 gulp
它假定每个 lambda 函数都在其自己的文件夹中实现,并且您需要定义您的 AWS 凭证配置文件。
我意识到这个答案对于原始发布者来说已经晚了很多年。但是我对打包 Lambda 函数有几乎相同的问题,所以为了后代,这里有一个解决方案不需要任何额外的 devDependencies(如 gulp 或 g运行t)并且只使用 npm pack
以及以下 package.json
(但假设您有 sed
和 zip
可用):
{
"name": "my-lambda",
"version": "1.0.0",
"scripts": {
"postpack": "tarball=$(npm list --depth 0 | sed 's/@/-/g; s/ .*/.tgz/g; 1q;'); tar -tf $tarball | sed 's/^package\///' | zip -@r package; rm $tarball"
},
"files": [
"/index.js",
"/lib"
],
"dependencies": {
"async": "*",
"collections": "*",
"underscore": "*",
"util": "*",
"xml2js": "*"
},
"bundledDependencies": [
"async",
"collections",
"underscore",
"util",
"xml2js"
],
"devDependencies": {
"chai": "*",
"mocha": "*"
}
}
鉴于上述 package.json,调用 npm pack
将生成一个 package.zip
文件,其中包含:
index.js
lib/
node_modules/
├── async/
├── collections/
├── underscore/
├── util/
└── xml2js/
files 数组是要包含的内容的白名单。在这里,它只是 index.js
和 lib
目录。
但是,npm 也会自动包含 package.json
、README
(以及 README.md
、CHANGELOG
(及其变体)和 LICENSE
等变体(以及替代拼写 LICENCE
),除非您明确排除它们(例如使用 .npmignore)。
bundledDependencies 数组指定要捆绑的包。在这种情况下,它是除 devDependencies 的 none 之外的所有依赖项。
最后,postpack 脚本在 npm pack
之后 运行 因为 npm pack
生成了一个 tarball,但是我们需要为 AWS Lambda 生成一个 zip。
https://hackernoon.com/package-lambda-functions-the-easy-way-with-npm-e38fc14613ba 提供了关于 postpack 脚本正在做什么的更详细的解释(也是一般方法的来源)。
npm-pack-zip 对我有用。
npm install --save-dev npm-pack-zip
为了使用 aws 发布整个 lambda,我在 package.json:
中使用了这个节点脚本
"publish": "npm-pack-zip && aws lambda update-function-code --function-name %npm_package_name% --zip-file fileb://%npm_package_name%.zip && rm %npm_package_name%.zip"
您可以使用 Zip-Build,这个小包将使用您 package.json
文件中的数据并创建一个名为 project-name
_version
.zip.
免责声明:我是这个库的开发者。
如何使用 zip-build
只需在您的项目中作为开发依赖安装:
$ npm install --save-dev zib-build
然后修改你的package.json
中的构建脚本,在末尾添加 && zip-build
,像这样:
"scripts": {
"build": your-build-script && zip-build
}
如果您的构建目录的名称不同于 build
,并且您想要的压缩文件目录的名称不同于 dist
,您可以提供目录名称作为 zip-build 的参数:
"scripts": {
"build": your-build-script && zip-build build-dirname zip-dirname
}
如果您是基于 UNIX 的,您也可以在您的脚本之一中使用 zip
命令:
"scripts": {
"zip": "zip -r build.zip build/"
"build": "build",
"build-n-zip": "build && zip
}
上面在根目录创建了一个 build.zip
,它是 /build
文件夹的压缩版本。
如果您想压缩多个 folders/files,只需将它们添加到末尾:
"scripts": {
"zip": "zip -r build.zip build/ some-file.js some-other-folder/"
}
有没有办法在构建时使用 Node.js 和 npm 自动压缩某些文件?
例如,我有一个项目,该文件结构如下所示:
Project/
--lib/
--node_modules/
--test/
--index.js
--package.json
我希望能够将 lib 文件夹、node_modules 和 index.js 中的某些模块压缩到某个 zip 存档中,以便将其上传到 AWS Lambda,例如。我不需要压缩测试文件夹或测试 Node.js 模块(mocha 和 chai)。我什至创建了一个 bash 脚本来生成 zip 文件,但是有没有办法在调用 'npm install' 时自动执行这个脚本?
这应该是一个标准问题,应该有一个标准的解决方案,但我找不到。
更新
感谢迈克尔,决定使用 gulp。这是我的脚本,以防其他人在 AWS Lambda 中需要它:
var gulp = require('gulp');
var clean = require('gulp-clean');
var zip = require('gulp-zip');
var merge = require('merge-stream');
gulp.task('clean', function () {
var build = gulp.src('build', {read: false})
.pipe(clean());
var dist = gulp.src('dist', {read: false})
.pipe(clean());
return merge(build, dist);
});
gulp.task('build', function() {
var index = gulp.src('index.js')
.pipe(gulp.dest('build'));
var lib = gulp.src('lib/**')
.pipe(gulp.dest('build/lib'));
var async = gulp.src('node_modules/async/**')
.pipe(gulp.dest('build/node_modules/async'));
var collections = gulp.src('node_modules/collections/**')
.pipe(gulp.dest('build/node_modules/collections'));
var underscore = gulp.src('node_modules/underscore/**')
.pipe(gulp.dest('build/node_modules/underscore'));
var util = gulp.src('node_modules/util/**')
.pipe(gulp.dest('build/node_modules/util'));
var xml2js = gulp.src('node_modules/xml2js/**')
.pipe(gulp.dest('build/node_modules/xml2js'));
return merge(index, lib, async, collections, underscore, util, xml2js);
});
gulp.task('zip', ['build'], function() {
return gulp.src('build/*')
.pipe(zip('archive.zip'))
.pipe(gulp.dest('dist'));
});
gulp.task('default', ['zip']);
你应该看看npm scripts。
您的存储库中仍然需要一个 bash 脚本,但它会在某些 npm
任务执行时自动触发。
我会使用 gulp 使用 gulp-sftp、gulp-tar 和 gulp-gzip 以及别名作为命令。在您的用户主文件夹中创建一个名为 .bash_aliases
的文件,其中包含
alias installAndUpload='npm install && gulp runUploader'
重新启动后,您可以使用此别名同时调用这两个操作。
gulp 文件可能看起来像这样
var gulp = require('gulp');
var watch = require('gulp-watch');
var sftp = require('gulp-sftp');
var gzip = require('gulp-gzip');
gulp.task('runUploader', function () {
gulp.src('.path/to/folder/to/compress/**')
.pipe(tar('archive.tar'))
.pipe(gzip())
.pipe(gulp.dest('path/to/folder/to/store')) // if you want a local copy
.pipe(sftp({
host: 'website.com',
user: 'johndoe',
pass: '1234'
}))
});
当然你也可以加上gulp-watch 自动创建tar/zip目录有变化就上传
如果您需要自动执行任务,请查看 Grunt or Gulp。
Grunt 需要的插件:
在 https://gist.github.com/ctulek/6f16352ebdfc166ce905
查看我的要点除了最初创建 lambda 函数(它只更新代码)之外,这对您提到的所有任务都使用 gulp
它假定每个 lambda 函数都在其自己的文件夹中实现,并且您需要定义您的 AWS 凭证配置文件。
我意识到这个答案对于原始发布者来说已经晚了很多年。但是我对打包 Lambda 函数有几乎相同的问题,所以为了后代,这里有一个解决方案不需要任何额外的 devDependencies(如 gulp 或 g运行t)并且只使用 npm pack
以及以下 package.json
(但假设您有 sed
和 zip
可用):
{
"name": "my-lambda",
"version": "1.0.0",
"scripts": {
"postpack": "tarball=$(npm list --depth 0 | sed 's/@/-/g; s/ .*/.tgz/g; 1q;'); tar -tf $tarball | sed 's/^package\///' | zip -@r package; rm $tarball"
},
"files": [
"/index.js",
"/lib"
],
"dependencies": {
"async": "*",
"collections": "*",
"underscore": "*",
"util": "*",
"xml2js": "*"
},
"bundledDependencies": [
"async",
"collections",
"underscore",
"util",
"xml2js"
],
"devDependencies": {
"chai": "*",
"mocha": "*"
}
}
鉴于上述 package.json,调用 npm pack
将生成一个 package.zip
文件,其中包含:
index.js
lib/
node_modules/
├── async/
├── collections/
├── underscore/
├── util/
└── xml2js/
files 数组是要包含的内容的白名单。在这里,它只是 index.js
和 lib
目录。
但是,npm 也会自动包含 package.json
、README
(以及 README.md
、CHANGELOG
(及其变体)和 LICENSE
等变体(以及替代拼写 LICENCE
),除非您明确排除它们(例如使用 .npmignore)。
bundledDependencies 数组指定要捆绑的包。在这种情况下,它是除 devDependencies 的 none 之外的所有依赖项。
最后,postpack 脚本在 npm pack
之后 运行 因为 npm pack
生成了一个 tarball,但是我们需要为 AWS Lambda 生成一个 zip。
https://hackernoon.com/package-lambda-functions-the-easy-way-with-npm-e38fc14613ba 提供了关于 postpack 脚本正在做什么的更详细的解释(也是一般方法的来源)。
npm-pack-zip 对我有用。
npm install --save-dev npm-pack-zip
为了使用 aws 发布整个 lambda,我在 package.json:
中使用了这个节点脚本 "publish": "npm-pack-zip && aws lambda update-function-code --function-name %npm_package_name% --zip-file fileb://%npm_package_name%.zip && rm %npm_package_name%.zip"
您可以使用 Zip-Build,这个小包将使用您 package.json
文件中的数据并创建一个名为 project-name
_version
.zip.
免责声明:我是这个库的开发者。
如何使用 zip-build
只需在您的项目中作为开发依赖安装:
$ npm install --save-dev zib-build
然后修改你的package.json
中的构建脚本,在末尾添加 && zip-build
,像这样:
"scripts": {
"build": your-build-script && zip-build
}
如果您的构建目录的名称不同于 build
,并且您想要的压缩文件目录的名称不同于 dist
,您可以提供目录名称作为 zip-build 的参数:
"scripts": {
"build": your-build-script && zip-build build-dirname zip-dirname
}
如果您是基于 UNIX 的,您也可以在您的脚本之一中使用 zip
命令:
"scripts": {
"zip": "zip -r build.zip build/"
"build": "build",
"build-n-zip": "build && zip
}
上面在根目录创建了一个 build.zip
,它是 /build
文件夹的压缩版本。
如果您想压缩多个 folders/files,只需将它们添加到末尾:
"scripts": {
"zip": "zip -r build.zip build/ some-file.js some-other-folder/"
}