Rolled up JSON assigned to the value "name" doesn't work in-browser
Psigio opened this issue · 2 comments
Hi,
I'm sure I'm doing something wrong, but I'm having trouble when rolling up a JSON value where it has a JSON key of "name":
{ "name" : { "key": "name-tag", "value": "Mr Jones" }, "address" : { "key": "address-tag", "value" : "1 Somewhere Street" } }
it rolls-up to the following:
var name = {"key":"name-tag","value":"Mr Jones"}; var address = {"key":"address-tag","value":"1 Somewhere Street"}; var fields = { name: name, address: address };
But it appears that name
is defined in the global scope of Chrome, so the value is not overwritten, and the fields.name
value is set to the globally scoped name
.
I've created a simple project which reproduces the situation at https://github.com/Psigio/rollup-plugin-json-test
Am I missing some configuration option perhaps? One approach I tried was editing the list of reserved words in the https://github.com/rollup/rollup-pluginutils package to include "name" and this seemed to address the issue - the output was:
var address = {"key":"address-tag","value":"1 Somewhere Street"}; var fields = { address: address, "name": {"key":"name-tag","value":"Mr Jones"} };
, but I wondered if there was a direct approach in rollup-plugin-json to achieve this?
Thanks!
Jon
The issue here is that you're writing to the global scope, rather than using the modules themselves. Let me walk you through the changes I made to your repro to get it to work as expected:
rollup.config.js
import nodeResolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import json from 'rollup-plugin-json';
export default {
+ format: 'iife',
+ moduleName: 'myBundle',
plugins: [
nodeResolve({ jsnext: true, main: true, browser: true }),
commonjs(),
json()
]
};
By default, Rollup will create a JavaScript module. But what we actually want is something that works as a regular <script>
tag – for that, we use the iife
format or Immediately Invoked Function Expression.
An IIFE keeps all of your code inside a function block, meaning that your variables are local, and not competing with things like window.name
:
(function () {
// your code in here is safe
}());
In your case, a JavaScript module looks a lot like a regular script (because you didn't have any import
or export
declarations for the bundle as a whole), which was the source of the confusion. Future versions of Rollup will warn you if you forget to include a valid format
option.
src/main.js
import preset_data from './data/data_index.js'
// Fields will have been imported via rollup
-function testFunction(){
+export function testFunction(){
return "The Name value is " + JSON.stringify(preset_data.fields.name) + " and the address is " + JSON.stringify(preset_data.fields.address);
}
-// Reference the function to avoid it being removed as it appears unused
-console.log(testFunction());
If you want to use a function (or any other value) outside of a module, you have to export it. If you want to use it outside of the bundle, you have to export it from the entry module (src/main.js
in your case). If something is exported, it won't be removed.
src/data/data_index.js
import { default as fields } from './data.json';
-export default preset_data = {
+export default {
fields: fields
};
You don't need to give names to default exports.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>Rollup-Plugin-Json-Test</title>
<script src='dist/bundle.js' type='text/javascript'></script>
</head>
<body>
<h1>Test</h1>
<p id="target">...</p>
<script>
- document.getElementById("target").innerHTML=testFunction();
+ document.getElementById("target").innerHTML=myBundle.testFunction();
</script>
</body>
</html>
The last step is to reference the testFunction
exported from the entry module. Because we gave the bundle a name – myBundle
– in the config file, and created an IIFE, we can reference it as a global variable.
Hope this helps!
Many thanks for the explanation @Rich-Harris, I thought I must have been doing something wrong!