Reputation: 2673
I have a json
file that is required somewhere in my node
script, but I do not want to have it bundled by rollup
. I want it to be treated as an "external". Every time the json
file changes, the script should be able to pick up the changes without rebuilding the bundle by rollup. Currently, it is "hard coded" in the bundle:
// ./src/index.js
const json = require('../example.json');
with ./example.json
as:
{
"exampleValue": "X"
}
returns a bundle that includes:
// ...
var exampleValue = "X";
var example = {
exampleValue: exampleValue
};
var example$1 = /*#__PURE__*/Object.freeze({
exampleValue: exampleValue,
default: example
});
// ...
I've tried to exclude it with rollup-plugin-json
, but as I could have expected, it throws:
[!] Error: Unexpected token (Note that you need rollup-plugin-json to import JSON files)
Is it possible to mark a json file as external, the same way you can mark external packages through the external
and output.paths
proeprties in the rollup configuration file?
Upvotes: 10
Views: 11008
Reputation: 115
I bumped into the same problem today. In the first few tries I put my json file into "external", but still got it built into final output. Then it occurred to me that, maybe I need to make that json file into a module first, then exclude it later. And the following worked for me.
Use "@rollup/plugin-json", so rollup can make that json into a module
import json from '@rollup/plugin-json'
Grab that json file location
const someJsonFile = join(dirname(fileURLToPath(import.meta.url)), 'pathToTheJsonFile')
Put it in external
const optForRollup = {
inputOptions: {
input: 'entryFile',
plugins: [
nodeResolve(),
commonjs(),
json(),
],
external: [
/node_modules/,
someJsonFile,
],
},
outputOptions: {
file: 'targetFile',
format: 'es',
sourcemap: true,
paths: {
[someJsonFile]: './some.json', // specify where that json is in runtime environment
}
},
}
Upvotes: 0
Reputation: 1295
@Dmitry's answer does not address the question, to whoever comes looking for the answer:
Firstly rollup will hardcode all values it finds, so e.g.
import {name, version} from '../package.json';
will get rolled up irrespective if you mark it external or not. In order to fix that, you can do:
async function foo() {
const {name, version} = await import('../package.json');
// ...
}
This will prevent values from being hardcoded but would bundle package.json
values anyways.
To mark it as external, in your rollup.config.js
do:
// ...
external: [
// ...
'../package.json' // exact match
// ...
]
// ...
This will change on how and where you import the json file. I tried with some implementation of wildcard externals, but that didn't work, maybe we can write for json.
But things since Node v17.5 have changed, since it will now drop ERR_IMPORT_ASSERTION_TYPE_MISSING error when bringing JSON files in.
you can have something like this:
async function foo() {
const {name, version} = await import('../package.json', { assert: { type: 'json' } });
// ...
}
You can also read the file and parse it as JSON, which worked for me:
function loadPkgInfo() {
const pkgFile = join(process.cwd(), 'package.json');
return JSON.parse(fs.readFileSync(pkgFile).toString());
}
Upvotes: 0
Reputation: 1716
The json plugin actually does the job for me. Here is my configuration file rollup-config.js
:
// import json from 'rollup-plugin-json'; Deprecated
import json from '@rollup/plugin-json';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import pkg from './package.json';
export default [
// browser-friendly UMD build
{
input: './index.js',
output: {
file: '../index.js',
name: 'Hy52fWS8r', // The global (never used) name for the factory of this UMD
format: 'umd'
},
plugins: [
resolve(),
commonjs(),
json({
compact: true
})
]
}
];
Source code:
// test.json
[1, 2, 3]
// index.js
const test = require('./test.json')
console.log(test) // Array(3) [ 1, 2, 3 ]
The rollup
's output looks as follows:
var test = [1,2,3];
var test$1 = /*#__PURE__*/Object.freeze({
'default': test
});
var test$2 = getCjsExportFromNamespace(test$1);
I don't know yet what is the rationale behind this. You can just ignore the test$1
and test$2
variables.
Upvotes: 7