How Do I Build A Json File With Webpack?
Solution 1:
There is actually a more elegant solution than the one by @user108471 (although it is inspired by it), and that is to use the copy-webpack-plugin
. With its transform
ability, you can add the desired values to the manifest.json
on the fly before copying it to its destination.
It has two advantages:
- it doesn't generate an extra unnecessary
manifest.js
-bundle (@bronson's solution also fixes this) - you don't need to
require
themanifest.json
in some other.js
-file (which would seem semantically backwards to me)
A minimal setup could be this:
webpack.config.js
// you can just require .json, saves the 'fs'-hasslelet package = require('./package.json');
functionmodify(buffer) {
// copy-webpack-plugin passes a buffervar manifest = JSON.parse(buffer.toString());
// make any modifications you like, such as
manifest.version = package.version;
// pretty print to JSON with two spaces
manifest_JSON = JSON.stringify(manifest, null, 2);
return manifest_JSON;
}
module.exports = {
// ...plugins: [
newCopyWebpackPlugin([
{
from: "./src/manifest.json",
to: "./dist/manifest.json",
transform (content, path) {
returnmodify(content)
}
}])
]
}
Solution 2:
Credit to Sean Larkin from the Webpack project for reaching out to me and helping me figure out how to get this done. I needed to create a custom loader to handle reading the existing manifest.json
and adding my fields of interest to it.
// File: src/manifest-loader.jsconst fs = require('fs');
// A loader to transform a partial manifest.json file into a complete// manifest.json file by adding entries from an NPM package.json.module.exports = function(source) {
const pkg = JSON.parse(fs.readFileSync('./package.json'));
const merged = Object.assign({}, JSON.parse(source), {
'name': pkg.name,
'description': pkg.description,
'version': pkg.version,
'author': pkg.author,
'homepage_url': pkg.homepage,
});
const mergedJson = JSON.stringify(merged);
// In Webpack, loaders ultimately produce JavaScript. In order to produce// another file type (like JSON), it needs to be emitted separately.this.emitFile('manifest.json', mergedJson);
// Return the processed JSON to be used by the next item in the loader chain.return mergedJson;
};
Then configure webpack to use my custom manifest-loader
.
// File: webpack.config.jsconst path = require('path');
module.exports = {
// Tell Webpack where to find our custom loader (in the "src" directory).resolveLoader: {
modules: [path.resolve(__dirname, "src"), "node_modules"]
},
// The path to the incomplete manifest.json file.entry: "./manifest.json",
output: {
// Where the newly built manifest.json will go.path: path.resolve(__dirname, 'dist'),
// This file probably won't actually be used by anything.filename: "manifest.js",
},
module: {
rules: [
{
// Only apply these loaders to manifest.json.test: /manifest.json$/,
// Loaders are applied in reverse order.use: [
// Second: JSON -> JS"json-loader",
// First: partial manifest.json -> complete manifest.json"manifest-loader",
]
}
]
}
};
The result, when running Webpack, is a dist/
directory containing manifest.js
and manifest.json
, with manifest.json
containing everything from the original, top-level manifest.json
plus the additional info from package.json
. The extra manifest.js
is a script that exposes the contents of manifest.json
to any other JavaScript in the project that wants it. This is probably not too useful, but a Chrome extension might conceivably want to require
this in a script somewhere to expose some of this information in a friendly way.
Solution 3:
My solution in Webpack 4 below. It's a generic solution for generating json files using Webpack loaders, but it works well for manifest.json files as well.
webpack.config.js
constExtractTextPlugin = require("extract-text-webpack-plugin");
const resolve = require("path").resolve;
module.exports = {
entry: {
entry: resolve(__dirname, "app/main.js"),
},
module: {
rules: [
{
test: /manifest\.js$/,
use: ExtractTextPlugin.extract({
use: [] // Empty array on purpose.
})
}
],
{
test: /\.png$/,
use: [{
loader: "file-loader",
options: {
context: resolve(__dirname, "app"),
name: "[path][name].[ext]",
publicPath: "/",
}
}]
}
},
output: {
filename: "[name].js",
path: resolve(__dirname, 'dist'),
},
plugins: [
new webpack.EnvironmentPlugin(["npm_package_version"]), // automagically populated by webpack, available as process.env.npm_package_version in loaded files.newExtractTextPlugin("manifest.json"),
]
};
app/main.js
const manifest = require('./manifest.js');
// Other parts of app …
app/manifest.js
const icon = require('./icon.png');
const manifestData = {
icon: {"128": icon}, // icon.png will be in the emitted files, yay!version: process.env.npm_package_version, // See webpack.config.js plugins// other manifest data …
};
// Whatever string you output here will be emitted as manifest.json:module.exports = JSON.stringify(manifestData, null, 2);
package.json dependencies
{
"extract-text-webpack-plugin": "4.0.0-beta.0",
"file-loader": "1.1.11",
"webpack": "4.12.0",
}
Solution 4:
const manifest = {
entry: './src/chrome_extension/dummy_index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'DELETED.js',
},
plugins: [
newCleanWebpackPlugin(),
newCopyWebpackPlugin({
patterns: [
{from: 'LICENSE.md'},
{from: 'assets/img/icon.png', to: `${ASSETS_PATH}/icon.png`},
{from: 'src/chrome_extension/manifest.json',
transform: function(manifestBuffer, path) {
const manifestString = manifestBuffer.toString()
.replace(/\$\{OPTIONS_PAGE_PATH\}/g, OPTIONS_PAGE_PATH)
.replace(/\$\{CONTENT_SCRIPT_PATH\}/g, CONTENT_SCRIPT_PATH)
.replace(/\$\{ASSETS_PATH\}/g, ASSETS_PATH);
returnBuffer.from(manifestString);
},
},
],
}),
newRemoveFilesWebpackPlugin({
after: {
log: false,
include: [
'dist/DELETED.js',
],
},
}),
],
stats: 'none',
mode: 'none',
};
Solution 5:
I was using your script enough that I published a somewhat modified version of it on NPM: https://github.com/bronson/manifest-package-loader
Hope it's as easy as yarn add -D manifest-package-loader
and updating your webpack.config.js.
Coincidentally, just this morning I ran across chem-loader, which might also work: https://github.com/mrmisterman/chem-loader
Post a Comment for "How Do I Build A Json File With Webpack?"