gregberge / svgr

Transform SVGs into React components 🦁
https://react-svgr.com
MIT License
10.51k stars 418 forks source link

Custom imports/exports don't work in v6.2.1 like the did in v5 #705

Open dPowNextdoor opened 2 years ago

dPowNextdoor commented 2 years ago

Custom imports/exports don't work in @svgr/webpack v6.2.1 like the did in v5

Bug Report

I cannot customize the exports of the resulting JavaScript/TypeScript SVGR output, regardless of any permutation of possible options/configs that may exist.

To Reproduce

Neither this:

loader: '@svgr/webpack',
options: {
    ref: true,
    memo: true,
    babel: false, // I don't want my babel.config.js overwritten since it has better support for old browsers
    jsxRuntime: 'automatic', // React >= v17 doesn't need `import React from 'react'`
    exportType: 'named', // Try to force the React component to be exported via named `ReactComponent`
    // ...
    template(componentInfo, svgrConfig) {
        const astBuilder = babelTemplateBuilder`
            ${componentInfo.imports};

            ${componentInfo.interfaces};

            const ${componentInfo.componentName} = (${componentInfo.props}) => (
                ${componentInfo.jsx}
            );

            export default const FileUrl = '${svgrConfig.options.state.filePath}';

            ${componentInfo.exports};
            `;

        return astBuilder;
    },
}

Nor this:

loader: '@svgr/webpack',
options: {
    template(componentInfo, svgrConfig) {
        componentInfo.exports?.push(babelTemplateBuilder`
            const FileUrl = '${svgrConfig.options.state.filePath}';
            export { FileUrl as default };
        `);

        const astBuilder = babelTemplateBuilder`
            ${componentInfo.imports};

            ${componentInfo.interfaces};

            const ${componentInfo.componentName} = (${componentInfo.props}) => (
                ${componentInfo.jsx}
            );

            ${componentInfo.exports};
            `;

        return astBuilder;
    },
}

Nor even this:

loader: '@svgr/webpack',
options: {
    template(componentInfo, svgrConfig) {
        componentInfo.exports?.push(babelTemplateBuilder`
            export default const FileUrl = '${svgrConfig.options.state.filePath}';
        `);

        // const astBuilder = babelTemplateBuilder(template);
        const astBuilder = babelTemplateBuilder`
            ${componentInfo.imports};

            ${componentInfo.interfaces};

            const ${componentInfo.componentName} = (${componentInfo.props}) => (
                ${componentInfo.jsx}
            );

            ${componentInfo.exports};

            export default const FileUrl = '${svgrConfig.options.state.filePath}';
            `;

        return astBuilder;
    },
}

Will work in order to get (what should obviously be the default behavior of) fixing v6's behavior to match that of the original, correct, v5 behavior of import SvgUrl, { ReactComponent as SvgComponent } from '/path/to/my-file.svg'.

Expected behavior

Users to be able to customize the exports such that they include multiple named and/or modified default exports.

e.g. I should be able to customize the template() to produce:

Link to repl or repo (highly encouraged)

  1. Clone my react-app-boilerplate repo.
  2. Add import * as SvgModule from '@/assets/react_logo.svg'; console.log(SvgModule); to src/components/Home/Home.jsx.
  3. Change the Webpack SVG config template() entry to use
// What I want, even implementing many parts of the docs on your website/ReadMe
const astArray = babelTemplateBuilder`
    ${componentInfo.imports};

    ${componentInfo.interfaces};

    function ${componentInfo.componentName}(${componentInfo.props}) {
        return (
            ${componentInfo.jsx}
        );
    }

    ${componentInfo.componentName}.displayName = '${componentInfo.componentName}';

    ${componentInfo.exports};

    // URL of the actual SVG file
    export const SvgUrl = SvgAssetUrl;

    // Add default export for ease of use
    export {
        ${svgDefaultExportReactComponent ? componentInfo.componentName : 'SvgUrl'} as default,
    };
`;

return astArray;

instead of

// What is currently my workaround
const astArray = babelTemplateBuilder\`yourString\`;

ast.push(babelTemplateBuilder('post-processing string with extra imports/exports'));`
  1. Watch the whole app crash and burn.

How would a user do this?

template clearly doesn't work and there isn't a way to modify the componentInfo.exports array nor specify multiple exportType config entries without running your own custom AST parser and appending it to the AST output-array.

Environment

npx envinfo --system --binaries --npmPackages @svgr/core,@svgr/cli,@svgr/webpack,@svgr/rollup --markdown --clipboard

## System:
 - OS: macOS 12.2.1
 - CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
 - Memory: 11.64 GB / 32.00 GB
 - Shell: 5.1.16 - /usr/local/bin/bash
## Binaries:
 - Node: 16.14.0 - ~/.nvm/current/bin/node
 - Yarn: 1.22.15 - ~/.yarn/bin/yarn
 - npm: 8.3.1 - ~/.nvm/current/bin/npm
## npmPackages:
 - @svgr/webpack: ^6.2.1 => 6.2.1 

Related

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.