Reputation: 21030
I am currently exploring Bucklescript/ReasonML with Svelte 3 for my next project. Typical Svelte component is a .svelte
file:
<script>
let name = 'world';
</script>
<h1>Hello world!</h1>
Instead, can I have script
tag with src
or equivalent to keep JS code in a separate file?
<script src='./some-file.js'></script>
By moving the js
code to a separate file, the target of the Bucklescript compiler (which is a JS file) could be used for the component.
Vue.js already supports this with their SFC .vue
file.
On a side note: I could use Vue.js for this but the presence Virtual DOM is problematic for legacy codebase. And, Svelte is diminishing at runtime and thus very much desirable. Also, the use
this
in Vue makes things awkward in Ocaml/Reason.
Upvotes: 16
Views: 4086
Reputation: 29615
This is possible with the svelte.preprocess API, which you'd most commonly reach via the preprocess
option in rollup-plugin-svelte or svelte-loader. Something like this should work (though I haven't tested it):
const path = require( 'path' )
const fs = require( 'fs' )
...
plugins: [
svelte({
// ...
preprocess: {
script: ({ content, attributes, filename }) => {
if ( 'string' === typeof attributes.src ) {
const file = path.resolve(path.dirname(filename), attributes.src);
const code = fs.readFileSync(file, 'utf-8');
return {code, dependencies: [file]};
}
}
}
})
]
Upvotes: 13
Reputation: 4072
As far as I know, this isn't possible right now.
What you could do is export everything you need from the js file, and then import them in the component: https://svelte.dev/repl/1d630ff27a0c48d38e4762cf6b0c2da5?version=3.7.1
<script>
import { name } from './mycode.js'
</script>
<h1>Hello {name}!</h1>
export let name = 'World';
However that would only be a partial solution as any mutation of data occurring within the file would not trigger a re-render of the DOM, as Svelte would not compile the .js file and would not be able to add its own code invalidating the values: https://svelte.dev/repl/c4b41b769ed747acb01a02a9af33e545?version=3.7.1
<script>
import { name, handleClick } from './mycode.js'
</script>
<h1 on:click={handleClick}>Hello {name}!</h1>
export let name = 'World';
export const handleClick = () => {
name = 'Everyone';
}
But that doesn't mean you can't be tricky if you are willing to go the extra mile to achieve this: https://svelte.dev/repl/8e259df629614ac99cb14cfae2f30658?version=3.7.1
<script>
import { name, handleClick } from './mycode.js'
const onClick = () => {
handleClick();
name = name;
}
</script>
<h1 on:click={onClick}>Hello {name}!</h1>
export let name = 'World';
export const handleClick = () => {
name = 'Everyone';
}
The extra line name = name
forcing the DOM update.
Upvotes: 2