transitive-bullshit / create-react-library

CLI for creating reusable react libraries.
https://transitivebullsh.it/javascript-dev-tools-in-2022
4.78k stars 300 forks source link

Adding assets #220

Open teehtheg opened 4 years ago

teehtheg commented 4 years ago

Is it possible to add assets to the library such as fonts or images?

Apparently create-react-app provides this feature in two different ways:

Would one of these approaches be feasible for create-react-library aswell?

transitive-bullshit commented 4 years ago

You should be able to import image files directly into your library from JS / TS. We're using this under the hood https://github.com/sormy/rollup-plugin-smart-asset

teehtheg commented 4 years ago

Oke, thats good to know! But what about fonts?

transitive-bullshit commented 4 years ago

If you list the extensions you'd like to bundle, I can add them to microbundle for you.

teehtheg commented 4 years ago

From the top of my head, I see two options:

  1. Use the plugin you're already using and adding the required file extensions to also handle fonts. I would recommend adding the following extensions to be on the safe side: [".eot", ".ttf", ".woff", ".svg", ".woff2"]

  2. Use rollup-plugin-copy and define a specific folder (e.g. "/assets") which will be copied into the build. This approach would not be restricted to certain file extensions, but it is not that "smart" in that it is copying over all files in this folder, and not just the ones which are referenced from your TS / JS code.

What's your opinion about that?

By the way: I really appreciate your willingness to extend / adjust your tool!

tbelch-at-eHealth-Tec commented 4 years ago

That would also be a big feature for me.

kzviagina commented 4 years ago

Any news on this? Is it possible?

kzviagina commented 4 years ago

In case someone needs to copy assets(fonts and images) referenced in css, you can add the following to microbundle-crl in postcss plugings section:

import postcssCopy from 'postcss-copy';

postcss({
    plugins: [
        ...
        postcssCopy({
            dest: dirname(options.output),
            template: 'assets/[hash].[ext][query]',
        }),
        ...
    ],
})

I also created PR with this change https://github.com/transitive-bullshit/microbundle/pull/3

rajuashok commented 4 years ago

Hey there, is there a workaround to be able to bundle fonts currently? I'm trying to do this now with the typescript version of create-react-library and getting an error.

Here's my typings.d.ts file:

declare module '*.woff';
declare module '*.woff2';

Here's my fonts.ts file:

import { createGlobalStyle } from 'styled-components';
import FFMarkBoldWoff from './ff-mark-bold.woff';

export default createGlobalStyle`
    @font-face {
        font-family: 'FF Mark';
        src: local('FF Mark'), local('FFMark'),
        url(${FFMarkBoldWoff2}) format('woff2'),
        url(${FFMarkBoldWoff}) format('woff');
        font-weight: 700;
        font-style: bold;
        font-display: swap;
    }
`;

The compiler complains with:

Error: Unexpected character '' (Note that you need plugins to import files that are not JavaScript)
at /Users/ashok/src/flixed/atoms/src/assets/fonts/ff-mark-bold.woff:1:4
1: wOFFWv��T`�GPOSl�#*�Pj'OS/2TU`uH�;VDMX�m�sXz�cmap�
kzviagina commented 4 years ago

@rajuashok for now the only way to do this is to fork the repository and add ability to bundle fonts referenced in js. Or alternatively you can reference fonts in css and use the example I mentioned in previous comment.

rajuashok commented 4 years ago

Hey @kzviagina thanks for the response! Sorry could you elaborate a bit on how to "add the ability to bundle fonts". Are you aware of exactly how to do that?

And if not, in your previous comment where exactly are you adding that snippet of code? There doesn't seem to be a config file for microbundle.

kzviagina commented 4 years ago

@rajuashok unfortunately it's impossible to "configure" this somehow with create-react-library at the moment. So the only way to make it work with fonts is to fork transitive-bullshit/microbundle, which is used by create-react-library to bundle resources and add functionality, that is required for you (in your case this is bundling fonts from js files). At least this is how I solved it for my case - bundle fonts, referenced in css.

rajuashok commented 4 years ago

Ah I see. Ok thank you so much that's very helpful!

rafaelguinho commented 3 years ago

Hello guys! using @kzviagina code I create a package https://www.npmjs.com/package/microbundle-crl-with-assets, just add it and update all references in your package.json.

keul commented 3 years ago

You should be able to import image files directly into your library from JS / TS

Although importing an image file works someway, it's not working for me to use the image in my code.

Using something like…

import iconImage from './images/area-icon.png';

Is translated to a var iconImage = "area-icon~eXbSLfTS.png"; in my UMD bundle, but this is not importing from the proper URL (as it starts from the HTML file).

ghost commented 3 years ago

@keul Have you found a solution for this? I'm having the same problem.

keul commented 3 years ago

@gilsonviana-oowlish I tried multiple approaches, no one applicable to every output format of the bundle.

A good partial approach was using import.meta.url then adding the filename from the import above to it, but this was not working everywhere (import.meta is only for modules).

I ended up by converting the image usage to a CSS background and including a full URL to unpkg in the CSS. Shame on me… but it works. 🤷‍♂️

ghost commented 3 years ago

@keul Thanks for your answer. I ended up using a CDN service like CloudFront, AWS S3, to host my assets.

mazurwiktor commented 3 years ago

You can export any asset from create-react-library to the create-react-app via two steps.

  1. import libraryAsset from "./asset.svg" Which is going to tell library bundler to add asset to the /dist directory.
  2. const asset = require(`./${libraryAsset}`) Which is going to tell react app bundler to add asset to the /build directory of an app.

Library should then use required asset e.g

<img src={asset}/>
hsyyid commented 3 years ago

@mazurwiktor Hi, I tried your solution and it worked like a charm for development. Problem is in deployment it seems like the assets don't resolve properly:

Could not find module in path: 'gluestick-elements/dist/arrow_forward_dark~feBKLjrO.svg' relative to '/node_modules/gluestick-elements/dist/index.modern.js'

CodeSandbox example: https://codesandbox.io/s/gluestick-demo-1c1dl

What's weird is in node_modules I can actually see all the assets have been included and downloaded.

unicornist commented 2 years ago

In case someone needs to copy assets(fonts and images) referenced in css, you can add the following to microbundle-crl in postcss plugings section:

import postcssCopy from 'postcss-copy';

postcss({
    plugins: [
        ...
        postcssCopy({
            dest: dirname(options.output),
            template: 'assets/[hash].[ext][query]',
        }),
        ...
    ],
})

I also created PR with this change transitive-bullshit/microbundle#3

based on the above answer I've managed to do it without forking or using the published fork of the fork of the fork in the answer below:

Hello guys! using @kzviagina code I create a package https://www.npmjs.com/package/microbundle-crl-with-assets, just add it and update all references in your package.json.

You can have a postcss.config.js and put this inside it:

module.exports = {
  plugins: {
    'postcss-copy': {dest: 'dist', template: 'assets/[hash].[ext][query]'}
  }
}

But my main problem with those forks was that I get errors regarding files not found and the way they are referenced (the built path). And since I now have a config file I can play with it. In my case I ended up with the following:

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
    'postcss-copy-assets': {base: 'dist'}
    // 'postcss-copy': {dest: 'dist/', template: 'assets/[hash].[ext][query]'}
  }
}

seemingly postcss-copy-assets does a better job and no need to worry about hashes bcs this is the dist of your library, people using it probably use webpack with create-react-app or anuglar or vue or whatever and it'll fix that.

resting commented 1 year ago

Hey there, is there a workaround to be able to bundle fonts currently? I'm trying to do this now with the typescript version of create-react-library and getting an error.

Here's my typings.d.ts file:

declare module '*.woff';
declare module '*.woff2';

Here's my fonts.ts file:

import { createGlobalStyle } from 'styled-components';
import FFMarkBoldWoff from './ff-mark-bold.woff';

export default createGlobalStyle`
    @font-face {
        font-family: 'FF Mark';
        src: local('FF Mark'), local('FFMark'),
        url(${FFMarkBoldWoff2}) format('woff2'),
        url(${FFMarkBoldWoff}) format('woff');
        font-weight: 700;
        font-style: bold;
        font-display: swap;
    }
`;

The compiler complains with:

Error: Unexpected character '' (Note that you need plugins to import files that are not JavaScript)
at /Users/ashok/src/flixed/atoms/src/assets/fonts/ff-mark-bold.woff:1:4
1: wOFFWv��T`�GPOSl�#*�Pj'OS/2TU`uH�;VDMX�m�sXz�cmap�

Trying to import custom font and having the same issue. Also aware this library is no longer maintained. But its legacy app. Adding postcss.config.sg as suggested here https://github.com/transitive-bullshit/create-react-library/issues/220#issuecomment-953450786 didn't work. Still getting the same error.

Are there any ways to import the fonts?