Skip to content
This repository has been archived by the owner on Jan 11, 2023. It is now read-only.

Make components/Foo.html a universally-available <Foo> component #216

Closed
Rich-Harris opened this issue Mar 26, 2018 · 4 comments
Closed

Comments

@Rich-Harris
Copy link
Member

This came up in Gitter the other day, and it would be a nice quality-of-life improvement. If every **/*.html file in a components directory was made available without needing to be explicitly imported, we could save ourselves some boilerplate.

It'd require a change to Svelte itself. I initially suggested something like this...

result = svelte.compile(source, {
  injectComponents: glob.sync('src/**/*.html').reduce((map, file) => {
    const name = path.basename(file).replace(/\.html$/, '');
    map[name] = path.relative(fileBeingCompiled, file);
    return map;
  }, {})
});

...though maybe the user should supply a search function instead? (The approach above wouldn't work if the contents of components changed during development, because webpack wouldn't know about it.) So perhaps this:

result = svelte.compile(source, {
  injectComponent: name => {
    const files = glob.sync(`**/${name}.html`, { cwd: 'components' });
    if (files.length > 1) throw new Error(`Multiple components called ${name}.html`);
    return files[0];
  }
});

Reglobbing each time isn't ideal, obviously, but in practice I don't think it'd be an issue (and you could supply a more sophisticated search function if you wanted).

In the context of a Sapper webpack config, it would mean adding something like this to both client and server configs:

const config = require('sapper/webpack/config.js');

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.html$/,
        exclude: /node_modules/,
        use: {
          loader: 'svelte-loader',
          options: {
            hydratable: true,
            cascade: false,
            store: true,
            hotReload: true,
+            injectComponent: config.inject()
          }
        }
      }
    ]
  },
  // ...
};

Alternatively, it could belong in preprocess, which would make it unnecessary to change anything in Svelte itself (though the implementation would be somewhat hackier, since it would presumably be based on naive string matching).

Of course, there is a good reason not to do any of this, which is that explicit > implicit, even when it's less convenient.

@Conduitry
Copy link
Member

I think there's still something to be set for this suggestion. It's slightly wonkier syntax, but it is more explicit, and doesn't require any conventions or special handling in Sapper.

@thgh
Copy link
Contributor

thgh commented Mar 27, 2018

Another approach would be that sapper dev --auto-import actually changes your source code and writes the boilerplate for you. (only right after saving, if the import is missing and if the component can be found in a specific folder)

@silentworks
Copy link
Contributor

I would rather it stay explicit. There is enough magic going on in Javascript already.

@Conduitry
Copy link
Member

The src/node_modules idea takes care of it being inconvenient to import from far away paths. Svelte 3 also naturally reduces some boilerplate when importing components, while also moving toward more things being explicit. Closing.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants