Fix Import a JSON file to JS code compatible with old and current browsers Step-by-Step Guide
๐จ Understanding the Error
Section titled โ๐จ Understanding the ErrorโImporting JSON files directly into JavaScript has historically been restricted due to security concerns (specifically the Same-Origin Policy) and the lack of a native module specification for non-JavaScript assets.
In modern environments, you might encounter Uncaught SyntaxError: Cannot use import statement outside a module or TypeError: Failed to fetch. In older browsers, the keyword import is simply not recognized, or the browser may block the request because the server did not return a valid application/json MIME type. As the ECMAScript specification evolved, the syntax shifted from Import Assertions to Import Attributes, creating a fragmentation gap between browser versions.
๐ Root Cause
Section titled โ๐ Root Causeโ| Cause | Impact | Technical Detail |
|---|---|---|
| MIME Type Mismatch | All Browsers | Server sends text/plain or text/html instead of application/json. |
| CORS Policy | Modern Browsers | Accessing a JSON file from a different domain without appropriate headers. |
| Syntax Evolution | Chromium 91-122 | Usage of assert { type: 'json' } which is now deprecated in favor of with. |
| Legacy Engines | IE11 / Old Safari | No support for fetch or ES6 Modules; requires XMLHttpRequest. |
| SOP Restrictions | Local Files | Browsers block file:// protocol access to JSON for security. |
๐ ๏ธ Step-by-Step Solutions
Section titled โ๐ ๏ธ Step-by-Step Solutionsโ1. The Modern Standard (Chrome 123+, Safari 17.2+, Firefox 126+)
Section titled โ1. The Modern Standard (Chrome 123+, Safari 17.2+, Firefox 126+)โUse Import Attributes. This is the current TC39 proposal stage 3+ standard.
// Modern syntax using 'with'import configData from './data.json' with { type: 'json' };
console.log(configData.name);2. The Fetch API (Universal Modern Support)
Section titled โ2. The Fetch API (Universal Modern Support)โIf you need to support browsers from the last 5-7 years without specific experimental flags, fetch is the most reliable asynchronous method.
async function loadConfig() { try { const response = await fetch('./data.json'); if (!response.ok) { throw new Error('Network response was not ok'); } const data = await response.json(); console.log(data); } catch (error) { console.error('Failed to load JSON:', error); }}
loadConfig();3. Legacy Browser Support (IE11 and Older)
Section titled โ3. Legacy Browser Support (IE11 and Older)โFor ancient environments, you must fallback to XMLHttpRequest (XHR). This does not support promises, so a callback pattern is required.
function loadJSONLegacy(url, callback) { var xhr = new XMLHttpRequest(); xhr.overrideMimeType("application/json"); xhr.open('GET', url, true); xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { callback(JSON.parse(xhr.responseText)); } }; xhr.send(null);}
loadJSONLegacy('./data.json', function(data) { console.log(data);});4. The Bundler Approach (Webpack / Vite / Rollup)
Section titled โ4. The Bundler Approach (Webpack / Vite / Rollup)โIn a professional production environment, you should let your build tool handle the import. This ensures compatibility across all browsers by inlining or transforming the JSON during the build process.
// This works in Vite/Webpack out of the boximport data from './data.json';
export const getAppConfig = () => { return data.version;};๐ก๏ธ Prevention and Best Practices
Section titled โ๐ก๏ธ Prevention and Best Practicesโ- Strict MIME Types: Ensure your web server (Nginx, Apache, or Express) sends the header
Content-Type: application/json. Without this, modern browsers will block the import for security reasons. - Use Build Tools: Use a transpiler like Babel or a bundler like Vite. They convert modern
importstatements into compatible code for older browsers automatically. - Graceful Degradation: When using the
fetchAPI, always implement a.catch()block ortry/catchto handle network failures or malformed JSON. - Local Testing: Browsers block JSON imports via the
file://protocol. Always use a local development server.- Quick Tip: Run
npx serveor use the VS Code extension Live Server (Alt + L Alt + O).
- Quick Tip: Run
- Prefer Attributes over Assertions: If targeting very recent browsers, move away from
assert { type: 'json' }and usewith { type: 'json' }to align with the latest V8 and SpiderMonkey implementations.