preact-router/match without babel

358 views Asked by At

Preact brags that it doesn't need build tools, but I don't see a way to make preact-router/match work. When I do:

<script type="module">
    import { Match } from 'https://unpkg.com/[email protected]/src/match.js';
</script>

it complains about the <Match> tags in the file:

Uncaught SyntaxError: expected expression, got '<'

And this one is apparently not a JavaScript module. Is there a way to make it work? Alternatively, what are the changes to be done to preact-router to make it work?

1

There are 1 answers

1
Harshal Patil On

The preact and preact-router are two different packages. preact-router itself has a dependency on preact. So, there is a dependency graph. To resolve this dependency graph without any builder within the browser itself, you need System.js or equivalent.

Alternately, instead of loading preact-router as a Module, import it as a normal self-bundled IIFE script as:

<script src="https://unpkg.com/[email protected]/dist/preact-router.js"></script>

Just ensure that before this script is loaded preact is also available globally. So, you should have:

<script src="https://unpkg.com/[email protected]/dist/preact.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/preact-router.js"></script>

Further explanation.

To use ES bundle, you should use from this location:

https://unpkg.com/browse/[email protected]/dist/preact-router.es.js

If you open this file you will notice that it imports from the preact library as:

import { Component, cloneElement, createElement, toChildArray } from 'preact';

When you load this as module type in browser and when browser encounters this import statement, it cannot figure from where it has to exactly get the preact dependency. Is it relative to the CDN? Is it relative to the domain from where you are loading the app? Or, is it relative to the path shown in address bar of the browser?

In case of TypeScript/Bable or front-end blunder like Webpack, it generally pulls it from node_modules using Node resolution algorithm. But browser doesn't have knowledge of node_modules. You have to teach it. At compile time, we use module bundler whereas at runtime, if you need to resolve modules, you need module loader like System.js.

There are four types of imports in ES Modules

// 1. Bare imports (Not supported by browsers directly)
import { Component } from 'preact';

// 2. Relative imports (Supported)
import { X } from './x.js';

// 3. Root relative imports (Supported)
import { X } from '/relative/to/site/root/x.js';

// 4. Absolute imports (Supported)
import { render } from 'https://unpkg.com/[email protected]/dist/preact.module.js';

Thus, even if your library is shipped as ES module, internally it has dependency on bare import specified 'preact' which browser cannot resolve.