Reputation: 96586
As far as I understand it, if I create an ES6 module, I can only import it from code that is itself a module. This means non-module code, i.e. inline Javascript, or the Chrome dev tools console can never access code that is in a module.
Is that true? Is there any way around this because it seems like a fairly extreme limitation.
Upvotes: 94
Views: 46946
Reputation: 5926
Some slightly more ergonomic versions, with correspondence between the different types of imports:
// import { namedExport1, namedExport2 } from 'https://example.com/lib.js'
const { namedExport1, namedExport2 } = await import('https://example.com/lib.js')
// import defaultExport from 'https://example.com/lib.js'
const { default: defaultExport } = await import('https://example.com/lib.js')
// import * as mod from 'https://example.com/lib.js'
const mod = await import('https://example.com/lib.js')
Edit: here's a little utility to do the conversion automatically:
function convertImports(imports, { verbose } = {}) {
return imports
.split(/\n(?=\s*import)/)
.map((statement) => {
const m = statement.match(/^\s*import\s*(?:(?<def>[$\p{L}\p{N}\p{M}]+)|\*\s+as\s+(?<wildcard>[$\p{L}\p{N}\p{M}]+)|(?<named>\{[^}]+\}))\s+from\s+(?<from>(?<quot>['"])[^'"]+\k<quot>)(?:\s+(?:with|assert)\s+(?<withProps>\{[^}]+\}))?[\s;]*$/u)
if (!m) return statement
const { groups: { def, wildcard, named, from, withProps } } = m
const vars = named
? named.replaceAll(/\s+as\s+/g, ': ')
: (wildcard ?? `{ default: ${def} }`)
return `${verbose ? statement.split('\n').map((x) => `// ${x}\n`).join('') : ''}const ${vars} = await import(${from}${withProps ? `, { with: ${withProps} }` : ''})`
})
.join(verbose ? '\n\n' : '\n')
}
// usage
const imports = `
import { namedExport1, namedExport2 } from 'https://example.com/lib.js'
import {
namedExport3 as three,
namedExport4 as four,
} from 'https://example.com/lib.js'
import defaultExport from 'https://example.com/lib.js'
import * as mod from 'https://example.com/lib.js'
import $ from 'https://example.com/jquery.js'
import data from 'https://example.com/data.json' with { type: 'json' }
`.trim()
console.log(convertImports(imports, { verbose: true }))
Upvotes: 6
Reputation: 21
You can import it using the dynamic import feature in the browser, but you need to know the named output path - for example:
const configPointModule = await import('/config-point/index.js')
const configPoint = globalThis.modules['config-point']
configPoint.exportedMethod()
Note that in that module I configured the export name to be 'modules.config-point', as seen below in an extract from the rollup config. There is nothing special about the name modules, I just prefer not to pollute the global namespace with more than 1 object, so I use the naming convention modules.<NAME>
instead of just <NAME>
export default {
input: "src/index.js",
output: [
{
file: pkg.main,
format: "umd",
name: "modules.config-point",
sourcemap: true
},
Upvotes: 0
Reputation: 1728
You can use dynamic import within Chrome's console.
import('path/to/module.js').then(m => module = m)
// [doSomething] is an exported function from [module.js].
module.doSomething()
Upvotes: 105
Reputation: 7995
You can await a dynamic import within Chrome's console:
const Module = await import('./path/to/module.js')
Module.doSomething()
That dynamic import is roughly equivalent to:
import * as Module from './path/to/module.js';
Module.doSomething()
Upvotes: 26
Reputation: 61
Carl's answer was quite helpful for me getting modules working in the console. However, since there are good reasons to not use window.* in your modules in production code, what I've started doing is:
window.myModule = myModule;
in the console.Upvotes: 0
Reputation: 31
There is a way to use the Chrome Dev Tools with ES6 modules, if you use VSCode and the Javascript Debugger for Chrome. I had some trouble to get it to work, but it was worth it. https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome
The VSCode debugger launches a new chrome window which is connected to the VSCode debugger. You can also use Chrome Dev Tools (F12) in this window as usual. It works with ES6 modules and you can set breakpoints, use the console, inspect variables, etc...
In case you have trouble to set up the debugger, this is how it worked for me:
CTRL+SHIFT+D
) -> select Add Configuration
from dropdown -> Select Chrome Launch
or Chrome Launch Legacy
to change "launch.json"my launch.json:
{
"name": "Launch Chrome Legacy",
"type": "chrome",
"request": "launch",
"url": "http://localhost:5000/auth/login",
"webRoot": "${workspaceFolder}",
"sourceMaps": true
},
{
"name": "Launch Chrome",
"request": "launch",
"type": "pwa-chrome",
"url": "http://localhost:5000/auth/login",
"webRoot": "${workspaceFolder}",
"sourceMaps": true
},
The key was to use "sourceMaps": true
and "url": "http://localhost:5000/auth/login"
instead of http://localhost:5000/blog"
, which is the page I actually want to debug. However, when the Debugger opens the new chrome window, my page was redirected to /auth/login
, so I had to use this url.
Legacy
version instead:
Turn off Debug › JavaScript: Use Preview
in the VSCode settings.Launch Chrome Legacy
from the Debug Window in VSCodeLoaded Scripts
Upvotes: 3
Reputation:
You can call functions contained in Javascript modules from the Chrome developer console using import, as in @Kin's answer.
If you get error "TypeError: Failed to resolve module specifier", try using the full URL for the module file. For example, on Windows 10 with IIS running locally, and Chrome 87, this works for me:
// Call doSomething(), an exported function in module file mymodule.js
import('http://localhost/mysite/myfolder/mymodule.js').then((m) => { m.doSomething(); });
Upvotes: 1
Reputation: 326
Hold and drag the module file into the chrome dev console.
Be sure to drag it to the input line section (after >
) of the console.
(This works on my Chrome 78 under Windows 10.)
Upvotes: 0
Reputation: 998
You can register the function or variable in the global namespace with a line like window.myFunction = myFunction
or window.myVariable = myVariable
. You can do this in the module where myFunction
or myVariable
are declared or do it in a separate module where they have been imported.
Once you've done this, you will be able to use myFunction
and myVariable
from the Chrome DevTools console.
For example:
import myModule from '/path/to/module.js';
window.myModule = myModule;
// in the console:
myModule.foo();
(Credit to @Evert for providing this solution in a comment, albeit in a rather roundabout way that took me a while to figure out.)
Upvotes: 27
Reputation: 99533
You can only import a module from other modules, because import
is a modules feature.
How did you 'import' before ES6 modules? You didn't, because it didn't exist. You can actually interact with an E6 Module the same was as you used interact between two independent non-module scripts.
Upvotes: 0