Обновление ссылок на файлы в json файле с помощью задания grunt
Я разработчик JavaScript и довольно новичок в создании процесса сборки с нуля. Я решил использовать Grunt для моего текущего проекта и создал GruntFile, который делает около 90% того, что мне нужно, и он отлично работает, за исключением одной проблемы. У меня есть несколько файлов JavaScript, на которые я ссылаюсь, пока я разрабатываю расширение chrome в файле manifest.json
. Для моего процесса сборки я объединяю все эти файлы и сворачиваю их в один файл, который будет включен в manifest.json
. Есть ли способ обновить ссылки на файлы в файле manifest.json
во время процесса сборки, чтобы он указывал на сокращенную версию?
Вот фрагмент файла манифеста src:
{
"content_scripts": [{
"matches": [
"http://*/*"
],
"js": [
"js/lib/zepto.js",
"js/injection.js",
"js/plugins/plugin1.js",
"js/plugins/plugin2.js",
"js/plugins/plugin3.js",
"js/injection-init.js"
]
}],
"version": "2.0",
}
У меня есть задача grunt, которая объединяет и уменьшает все перечисленные выше файлы js в один файл с именем injection.js
и хочет, чтобы задача grunt могла изменить файл манифеста, чтобы он выглядел следующим образом:
{
"content_scripts": [{
"matches": [
"http://*/*"
],
"js": [
"js/injection.js"
]
}],
"version": "2.0",
}
На данный момент у меня есть 2 версии файла манифеста, один для dev и один для сборки, в процессе сборки он копирует версию сборки. Это означает, что мне нужно поддерживать 2 версии, которые я бы предпочел не делать. Есть ли способ сделать это более элегантно с Grunt?
Ответы
Ответ 1
Grunt
дает свой собственный api для чтения и записи файлов, я чувствую, что лучше, чем другие зависимости вроде fs
:
Отредактируйте/обновите файл json с помощью grunt с помощью команды grunt updatejson:key:value
после того, как эта задача находится в вашем файле gruntjs
grunt.registerTask('updatejson', function (key, value) {
var projectFile = "path/to/json/file";
if (!grunt.file.exists(projectFile)) {
grunt.log.error("file " + projectFile + " not found");
return true;//return false to abort the execution
}
var project = grunt.file.readJSON(projectFile);//get file as json object
project[key]= value;//edit the value of json object, you can also use projec.key if you know what you are updating
grunt.file.write(projectFile, JSON.stringify(project, null, 2));//serialize it back to file
});
Ответ 2
Я делаю что-то подобное - вы можете загрузить манифест, обновить содержимое и затем снова сериализовать его. Что-то вроде:
grunt.registerTask('fixmanifest', function() {
var tmpPkg = require('./path/to/manifest/manifest.json');
tmpPkg.foo = "bar";
fs.writeFileSync('./new/path/to/manifest.json', JSON.stringify(tmpPkg,null,2));
});
Ответ 3
Я не согласен с другими ответами здесь.
1) Зачем использовать grunt.file.write
вместо fs
? grunt.file.write
является просто оболочкой для fs.writeFilySync
(см. код здесь).
2) Зачем использовать fs.writeFileSync
, когда хрюкать делает так просто делать асинхронно? Нет никаких сомнений в том, что вам не нужен async в процессе сборки, но если это легко сделать, почему бы вам не так? (Это, по сути, только пара символов длиннее, чем реализация writeFileSync
.)
Я бы предложил следующее:
var fs = require('fs');
grunt.registerTask('writeManifest', 'Updates the project manifest', function() {
var manifest = require('./path/to/manifest'); // .json not necessary with require
manifest.fileReference = '/new/file/location';
// Calling this.async() returns an async callback and tells grunt that your
// task is asynchronous, and that it should wait till the callback is called
fs.writeFile('./path/to/manifest.json', JSON.stringify(manifest, null, 2), this.async());
// Note that "require" loads files relative to __dirname, while fs
// is relative to process.cwd(). It easy to get burned by that.
});