Webpack Theme Loader

I would like to execute the following structure:

  • button.core.jsx
  • button.theme-a.jsx
  • button.theme-b.jsx

To take React as an example, I would like to do the following in button.core.jsx :

 import React from 'react'; import Themed from './button.[theme]'; export default class Button extends React.Component { render() { if (Themed) { return <Themed />; } return <button>default button</button>; } } 

In other words, I want to define a theme in my webpack.config.js and load this file if it exists. If not, change the default behavior. I think it will be a very powerful setting!

I searched to create a custom bootloader, but haven't achieved anything so far. Can someone point me in the right direction?

+5
source share
1 answer

I have a job writing a custom "resolver":

 const ThemeResolver = { apply: function(resolver) { resolver.plugin('file', function(req, cb) { if (req.request.indexOf('[theme]') == -1) { return cb(); } const defaultFile = req.request.replace('[theme]', 'Default'); const themedFile = req.request.replace('[theme]', process.env.THEME); req.request = themedFile; this.doResolve(['file'], req, (err) => { if (!err) { return cb(); } req.request = defaultFile; this.doResolve(['file'], req, cb); }) }); } }; module.exports = { // ... plugins: [ new webpack.ResolverPlugin([ThemeResolver]), ] // ... }; 

It tries to resolve a file with [theme] in its path to a path with a theme defined as an environment variable. If it fails, it will replace the default file instead. Thus, I can require a theme file as follows:

import Presentation from './button-[theme]'

The main component turned out to be a little different than in my question, but I'm actually quite pleased with it:

 import React from 'react'; import Presentation from './button-[theme]'; export default class Button extends React.Component { onClick = (e) => console.log('some logic'); render() { return <Presentation onClick={ this.onClick } />; } } 

The logic of this button component can be inside button.core.jsx , while the presentation will be processed by one of these components:

 THEME=theme-a npm start // button-[theme] resolves to button-theme-a.jsx THEME=theme-c npm start // button-[theme] resolves to button-default.jsx 

Disclaimer: I have not used this in a large-scale or production environment, but it seems to work in a small POC. Please let me know if I am doing something unreasonably!

+4
source

Source: https://habr.com/ru/post/1241531/


All Articles