15

I'm a JavaScript developer and fairly new to creating a build process from scratch. I chose to use Grunt for my current project and have created a GruntFile that does about 90% of what I need it to do and it works great, except for this one issue. I have several JavaScript files that I reference while I'm developing a chrome extension in the manifest.json file. For my build process I am concatenating all of these files and minifying it into one file to be included in manifest.json. Is there anyway to update the file references in the manifest.json file during the build process so it points to the minified version?

Here is a snippet of the src manifest file:

{
    "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",
}

I have a grunt task that concatenates and minifies all the js files listed above into one file called injection.js and would like a grunt task that can modify the manifest file so it looks like this:

{
    "content_scripts": [{
        "matches": [
            "http://*/*"
        ],
        "js": [
            "js/injection.js"
        ]
    }],
    "version": "2.0",
}

What I've done for now is have 2 versions of the manifest file, one for dev and one for build, during the build process it copies the build version instead. This means I need to maintain 2 versions which I'd rather not do. Is there anyway to do this more elegantly with Grunt?

4

3 回答 3

31

Grunt提供了自己的 api 用于读取和写入文件,我觉得这比其他依赖项更好:将此任务放入 gruntjs 文件后,fs使用 grunt 命令编辑/更新 json文件grunt updatejson:key:value

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

    });
于 2014-02-25T10:06:12.790 回答
11

我做了类似的事情 - 你可以加载你的清单,更新内容然后再次序列化它。就像是:

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));
});
于 2013-06-11T19:40:43.000 回答
0

我不同意这里的其他答案。

1)为什么使用grunt.file.write而不是fsgrunt.file.write只是一个包装器 fs.writeFilySync(见这里的代码)。

2) 为什么要fs.writeFileSync在 grunt 让异步处理事情变得非常容易时使用?毫无疑问,您在构建过程中不需要异步,但如果它很容易做到,为什么不呢?(实际上,它只比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's easy to get burned by that.
});
于 2014-09-13T19:52:02.363 回答