Chrome拡張機能で使用されるmanifest.json
ファイルを「スマートな」プログラム的な方法でアセンブルしたい。依存関係の解決にnpmを使用している。 package.json
には、「名前」、「説明」、「バージョン」など、manifest.json
ファイルとの共有フィールドがいくつか含まれています。
すべてのChrome固有のものを含む、部分的なmanifest.json
ファイルのようなものを定義する方法はありますか?これはGulpではかなり単純であることがわかりました。
var gulp = require('gulp');
var fs = require('fs');
var jeditor = require('gulp-json-editor');
gulp.task('manifest', function() {
var pkg = JSON.parse(fs.readFileSync('./package.json'));
gulp.src('./manifest.json')
.pipe(jeditor({
'name': pkg.name,
'description': pkg.description,
'version': pkg.version,
'author': pkg.author,
'homepage_url': pkg.homepage,
}))
.pipe(gulp.dest("./dist"));
});
この目的のために設計されたnpmパッケージがそこにあるとしても、誰かがこのようなことが一般的にどのように行われるかを私に説明できますか? Webpack 2には組み込みのjsonローダーがあることは知っていますが、このような場合にどのように使用されるかはわかりません。
WebpackプロジェクトのSean Larkinが私に連絡を取り、これを行う方法を理解してくれたことを感謝します。既存のmanifest.json
の読み取りと、対象となるフィールドの追加を処理するカスタムローダーを作成する必要がありました。
// File: src/manifest-loader.js
const 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;
};
次に、カスタムmanifest-loader
を使用するようにwebpackを構成します。
// File: webpack.config.js
const 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",
]
}
]
}
};
Webpackを実行すると、結果はdist/
ディレクトリにmanifest.js
とmanifest.json
が含まれ、manifest.json
には元のトップレベルのmanifest.json
とpackage.json
からの追加情報。追加のmanifest.js
は、manifest.json
の内容を、それを必要とするプロジェクト内の他のJavaScriptに公開するスクリプトです。これはおそらくあまり役には立ちませんが、Chrome拡張機能はスクリプトのどこかでこれをrequire
にして、この情報の一部をわかりやすい方法で公開したい場合があります。
@ user108471によるソリューションよりも実際にはよりエレガントなソリューションがあり(それに触発されていますが)、それは copy-webpack-plugin
を使用することです。 transform
機能により、目的の値をコピー先にコピーする前に、オンザフライでmanifest.json
に必要な値を追加できます。
これには2つの利点があります。
manifest.js
- bundleは生成されません( @ bronsonのソリューション もこれを修正します)manifest.json
ファイルでrequire
.js
を実行する必要はありません(意味的に後方に見えるようになります)最小限の設定は次のようになります:
webpack.config.js
// you can just require .json, saves the 'fs'-hassle
let package = require('./package.json');
function modify(buffer) {
// copy-webpack-plugin passes a buffer
var 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: [
new CopyWebpackPlugin([
{
from: "./src/manifest.json",
to: "./dist/manifest.json",
transform (content, path) {
return modify(content)
}
}])
]
}
以下のWebpack 4での私の解決策。これは、Webpackローダーを使用してjsonファイルを生成するための一般的なソリューションですが、manifest.jsonファイルでも同様に機能します。
const ExtractTextPlugin = 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.
new ExtractTextPlugin("manifest.json"),
]
};
const manifest = require('./manifest.js');
// Other parts of app …
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);
{
"extract-text-webpack-plugin": "4.0.0-beta.0",
"file-loader": "1.1.11",
"webpack": "4.12.0",
}
Webpack 4を使用している場合は、非常に簡単です。明示的なjsonローダーを指定する必要はありません
注:ここではすべてを1つのhtmlファイルにバンドルしていますが、webpack.config.jsファイルにjsonローダーがないことがわかります
webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: [/node_modules/],
use: [{
loader: 'babel-loader'
}],
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
test: /\.ico$/,
use: ["file-loader"]
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
}
],
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html",
inlineSource: '.(js|css)$'
}),
new HtmlWebpackInlineSourcePlugin(),
],
devServer: {
compress: true,
disableHostCheck: true,
}
}
私のapp.jsでは私はちょうど使用します
import data from './data/data.json'
私はあなたのスクリプトを十分に使っていたので、NPMにそれの多少変更されたバージョンを公開しました: https://github.com/bronson/manifest-package-loader
yarn add -D manifest-package-loader
と同じくらい簡単で、webpack.config.jsを更新してください。
偶然にも、今朝ちょうど私はchem-loaderに遭遇しましたが、これも機能する可能性があります: https://github.com/mrmisterman/chem-loader