react rollup no styling with tailwind css and css - javascript

I want to build a npm package with rollup but the styling is not available. I want to use style with tailwindcss, css or scss.
I created a repo with demo code to demonstrate this issue.
You can do the steps in README.md and then you will see that the styling is not applied
Repo
This is my rollup.config.js
import babel from "#rollup/plugin-babel";
import image from "#rollup/plugin-image";
import json from "#rollup/plugin-json";
import commonjs from "rollup-plugin-commonjs";
import { nodeResolve } from "#rollup/plugin-node-resolve";
import replace from "#rollup/plugin-replace";
import sourcemaps from "rollup-plugin-sourcemaps";
import postcss from "rollup-plugin-postcss";
const input = "src/index.jsx";
var MODE = [
{
fomart: "es",
},
];
var config = [];
MODE.map((m) => {
var conf = {
input: input,
output: {
dir: `dist`,
format: m.fomart,
sourcemap: true,
},
inlineDynamicImports: true,
plugins: [
replace({
"process.env.NODE_ENV": JSON.stringify("development"),
}),
nodeResolve({
extensions: [".js", ".jsx"],
}),
postcss({
minimize: true,
modules: true,
extract: true,
}),
json(),
image(),
babel({
exclude: "node_modules/**",
plugins: ["#babel/transform-runtime"],
babelHelpers: "runtime",
}),
commonjs({
include: "node_modules/**",
}),
sourcemaps(),
],
};
config.push(conf);
});
export default [...config];

The Bootstrap styles aren't working because of the PostCSS "modules" option in rollup config. This option prefixes the class names (you can see it in dist/index.css generated file, by looking for "bootstrap-min") in order to avoid conflicts, but in our case we want Bootstrap styles to be global.
postcss({
minimize: true,
modules: true, // <--- this line
extract: true,
}),
by removing it, the Bootstrap CSS is generated without any CSS module prefix.
Regarding Tailwind, you have to install the compatibility build of Tailwind and configure its PostCSS plugin in the rollup config, like described in https://samrobbins.uk/blog/tailwind-component-library

Related

Rollup is importing util

I am building a library to be used to call api's
I am using rollup to bundle all the files into one file, the issue is its adding this line
import util from 'util';
not sure what it does, I am not using anything from util
below is my rollup config file
import nodeGlobals from "rollup-plugin-node-globals";
import commonjs from "rollup-plugin-commonjs";
import uglify from "rollup-plugin-uglify";
import babel from "rollup-plugin-babel";
import replace from "rollup-plugin-replace";
import resolve from "rollup-plugin-node-resolve";
import rollupJson from "rollup-plugin-json";
export default [
{
input: 'src/config.js',
output: [
{
name:"asd",
file: 'dist/bundle-b2.js',
format: 'es',
}
],
plugins: [
babel({
babelrc: false,
presets: [
["airbnb",{"modules":false}],
["env",{"modules":false,"useBuiltIns": false}],
["es2015",{"modules":false}],
['stage-2']],
exclude:[
'node_modules/**',
],
plugins: ['external-helpers', ["transform-builtin-extend", {
globals: ["Error", "Array"],
}]],
externalHelpers: true,
runtimeHelpers: true,
}),
resolve({
jsnext: true,
preferBuiltins: true,
browser: true,
}),
commonjs({
include: 'node_modules/**'
}),
nodeGlobals(
{
process:true,
global:false,
Buffer:false
}
),
rollupJson({compact: true
}),
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
]
}
];
any help please ?
Thanks
Probably what is happening is one of your dependencies uses NodeJS's util built-in library. Even though you don't use util and you might not even use functionality from that dependency that uses util, Rollup still adds the import to the bundle.
If that is indeed the case, you'll need another plugin (like rollup-plugin-polyfill-node) that can handle these imports and give you something that either mimics or at least fakes functionality so that the build can complete properly.

rollup not detecting #import syntax for scss files

i need rollup to bundle my sass files, like variables, mixins etc.
index.scss contains
#import "./scss/variables.scss";
and index.ts contains
import "./index.scss";
export { Button } from "./components/Button";
however the bundle does NOT have any code from variables.scss, and if i use a variable inside of say Button.scss i get this error
[!] (plugin postcss) Error: Undefined variable: "$shady-lady".
my rollup config
export default {
input: "./src/index.ts",
output: [
{
file: packageJson.main,
format: "cjs",
sourcemap: true,
},
{
file: packageJson.module,
format: "esm",
sourcemap: true,
},
],
plugins: [
resolve(),
cleaner({
targets: ["./lib"],
}),
postcss({
extract: true,
modules: true,
minimize: true,
plugins: [postcssImport(), autoprefixer()],
extensions: [".scss"],
}),
peerDepsExternal(),
commonjs(),
typescript({
exclude: ["**/*.stories.tsx", "**/*.test.tsx"],
}),
],
};
so the problem wasn't with the #import syntax. it was rollup not handling global resources files.
the solution was to remove the import './index.scss' from index.ts and just use this package
https://github.com/hytromo/rollup-plugin-postcss-retain-sass-data#readme

How to propperly build react modular library

I'm trying to create a react components library which is based on Typescript and SASS. The components library will be used in multiple other typescript projects, so type exports are needed as well. Ideally I want to mimic something like "Material-UI"/"React-Bootrap" libraries dist output solutions.
Example project structure:
|Tabs
+--Tabs.tsx
+--Tabs.scss
+--index.tsx
index.tsx
index.tsx
export { Tabs } from './Tabs/Tabs';
Tabs/index.tsx
import React from 'react';
import './Tabs.scss';
interface TabsProps {
...
}
export const Tabs: React.FC<TabsProps> = (props) => <div>...</div>
Tabs/index.tsx
export { Tabs } from './Tabs';
Expected built dist structure should mimic the src structure:
|Tabs
+--Tabs.js
+--Tabs.d.ts
+--index.js
+--index.d.ts
index.js
index.tsx
I tried analyzing open source projects and see how they are building the libraries, however I could not find libraries using the same approaches that I could reuse.
The solutions I've tried:
Webpack: While I could compile typescript and sass files the webpack would always emit only one file specified in the output section, which usually would be bundled and I would loose the ability to import single component from a specific component's module. I know I can specify multiple entry points, but the project will be having a lot of exports and manually specifying them is not an option...
Example config I tried:
const path = require('path');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
module.exports = {
entry: './src/index.tsx',
module: {
rules: [
// sass-loader is not used here yet, but should be once desired structure can be reached
{
test: /\.tsx?$/,
loader: 'babel-loader',
},
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ test: /\.js$/, loader: "source-map-loader" }
]
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
extensions: [".tsx", ".ts", ".js"],
plugins: [
new TsconfigPathsPlugin({ configFile: "./tsconfig.build.json" })
]
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
}
};
Rollup: Similar situation as webpack
Example config that I tried:
// rollup.config.js
import babel from 'rollup-plugin-babel';
import sass from 'rollup-plugin-sass';
import nodeResolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import react from 'react';
import reactDom from 'react-dom';
const babelOptions = {
exclude: /node_modules/,
// We are using #babel/plugin-transform-runtime
runtimeHelpers: true,
extensions: ['.js', '.ts', '.tsx'],
configFile: './babel.config.js',
};
const nodeOptions = {
extensions: ['.js', '.tsx', '.ts'],
};
const commonjsOptions = {
ignoreGlobal: true,
include: /node_modules/,
namedExports: {
react: Object.keys(react),
'react-dom': Object.keys(reactDom)
},
};
export default {
input: 'src/index.tsx',
output: {
name: '[name].js',
dir: 'dist',
format: 'umd',
sourcemap: true,
},
plugins: [
nodeResolve(nodeOptions),
sass(),
commonjs(commonjsOptions),
babel(babelOptions)
],
};
Babel: I managed to compile the typescript code however once I came close to transpiling SASS files I would end up with suggestions to use webpack for that...
TSC: I successfully could run the typescript compiler and it would compile all the files without problems and would maintain the same structure. However TSC does not support other transpiling options so after a lot of searches I would end up with suggestions to use webpack and "ts-loader" or "babel-loader"..
tsconfig:
{
"extends": "../../tsconfig.build.json",
"compilerOptions": {
"lib": [ "es2015", "dom" ],
"outDir": "dist",
"baseUrl": ".",
"declaration": true,
"composite": true,
"module": "commonjs",
"target": "es5"
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist"
]
}
Desirced solution:
I should be able after compiling the library and installing it in another project be able to run the following:
import { Tabs } from 'my-lib/Tabs';
import { Tabs } from 'my-lib';
After a lot of playing around I managed to produce the wanted result with rollup. The only downside of the current configuration is that it does not support newly added files in the --watch mode. The magic setting is under the output.preserveModules
Config:
// rollup.config.js
import commonjs from '#rollup/plugin-commonjs';
import typescript from '#rollup/plugin-typescript';
import postcss from 'rollup-plugin-postcss';
import postcssUrl from 'postcss-url';
import resolve from "#rollup/plugin-node-resolve";
import peerDepsExternal from "rollup-plugin-peer-deps-external";
export default {
input: 'src/index.tsx',
output: {
dir: 'dist',
format: 'es',
preserveModules: true,
sourcemap: true,
},
plugins: [
resolve(),
peerDepsExternal(),
commonjs(),
typescript({
tsconfig: 'tsconfig.build.json'
}),
postcss({
minimize: true,
modules: {
generateScopedName: "[hash:base64:5]"
},
plugins: [
postcssUrl({
url: "inline"
})
]
}),
],
};
I hope this config can help others as well
You can checkout this repo. I made some changes for building a lib.
https://github.com/21paradox/react-webpack-typescript-starter
To use a library like below:
import Input from 'my-custom-ui/entry/Input';
import { Input } from 'my-custom-ui';
After doing a lot of searching, I ended up writing a plugin to manually generate the webpack entry code that webpack needed (for building a ui library).
The multiple entry + manualy generated entry file seems to be working for component seperate & no redudant code. This is also very helpful if you want to build a vue based libray.

Exporting sass/css in npm module - Rollup

Overview
I'm trying to write a react based npm module. I've configured my environment using rollup and I can see the js/d.ts/css files being created in the build.
Issue
Using npm link, I was testing in a separate project. Now I'm able to import the js file, but I'm unable to import the css file.
Here is my rollup configuration (rollup.config.js)
import typescript from "rollup-plugin-typescript2";
import commonjs from "rollup-plugin-commonjs";
import external from "rollup-plugin-peer-deps-external";
import resolve from "rollup-plugin-node-resolve";
import sass from 'rollup-plugin-sass';
import pkg from "./package.json";
export default {
input: "src/index.tsx",
output: [{
file: pkg.main,
format: "cjs",
exports: "named",
sourcemap: true
},
{
file: pkg.module,
format: "es",
exports: "named",
sourcemap: true
}
],
plugins: [
external(),
resolve({
browser: true,
extensions: ['.mjs', '.js', '.jsx', '.json', '.scss', '.css']
}),
sass({
output: "autocomplete_style.css"
}),
typescript({
rollupCommonJSResolveHack: true,
exclude: "**/__tests__/**",
clean: true
}),
commonjs({
include: ["node_modules/**"],
namedExports: {
"node_modules/react/react.js": [
"Children",
"Component",
"PropTypes",
"createElement"
],
"node_modules/react-dom/index.js": ["render"]
}
})
]
};
Please note, I'm able to create a successful build. The issue is just with the import of the generated css file.

Rollup.js - have PostCSS process whole bundle.css instead of individual files from rollup-plugin-svelte

I've tried several guides and many configurations, but can't get my rollup, postcss, and svelte bundle process to work quite right.
Right now the svelte plugin is extracting the css from my .svelte files and emitting it to the posctcss plugin, but it's doing it one file at a time instead of the entire bundle. This makes it so some functions in the purgecss and nanocss postcss plugins don't completely work because they need the entire bundle to do things like remove duplicate/redundant/unused css rules.
// rollup.config.js
import svelte from 'rollup-plugin-svelte'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import livereload from 'rollup-plugin-livereload'
import { terser } from 'rollup-plugin-terser'
import rollup_start_dev from './rollup_start_dev'
import builtins from 'rollup-plugin-node-builtins'
import postcss from 'rollup-plugin-postcss'
const production = !process.env.ROLLUP_WATCH
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/bundle.js',
},
plugins: [
svelte({
dev: !production,
emitCss: true,
}),
postcss({
extract: true,
sourceMap: true,
}),
builtins(),
resolve({
browser: true,
dedupe: importee =>
importee === 'svelte' || importee.startsWith('svelte/'),
}),
commonjs(),
!production && rollup_start_dev,
!production && livereload('public'),
production && terser(),
],
watch: {
clearScreen: false,
},
}
// postcss.config.js
const production = !process.env.ROLLUP_WATCH
const purgecss = require('#fullhuman/postcss-purgecss')
module.exports = {
plugins: [
require('postcss-import')(),
require('tailwindcss'),
require('autoprefixer'),
production &&
purgecss({
content: ['./src/**/*.svelte', './src/**/*.html', './public/**/*.html'],
css: ['./src/**/*.css'],
whitelistPatterns: [/svelte-/],
defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || [],
}),
production &&
require('cssnano')({
preset: 'default',
}),
],
}
How can I have rollup pass the entire bundle.css to postcss instead of one "file" at a time?
I had the same problem, preprocess goes file by file, so I had to actually include all my mixins and vars in every file, which is absolutely not a good solution.
So for me the first solution was to remove postcss from sveltePreprocess, not emit the css file and to use postcss on the css bundle, that you get in the css function from svelte.
You can then or (1) use postcss directly in the css function of svelte, and then emit the resulting css file in your dist directory, or (2) you can emit this file in a CSS directory, and have postcss-cli watch this directory and bundle everything
Solution 1
// rollup.config.js
// rollup.config.js
import svelte from 'rollup-plugin-svelte';
import resolve from 'rollup-plugin-node-resolve';
import postcss from 'postcss';
import postcssConfig from './postcss.config.js';
const postcssPlugins = postcssConfig({});
const postcssProcessor = postcss(postcssPlugins);
export default {
input: 'src/main.js',
output: {
file: 'public/bundle.js',
format: 'iife',
},
plugins: [
svelte({
emitCss: false,
css: async (css) => {
const result = await postcssProcessor.process(css.code);
css.code = result.css;
css.write('public/bundle.css');
},
}),
resolve(),
],
};
and my postcss.config.js which returns a function that return an array of plugins:
export default (options) => {
const plugins = [
require('postcss-preset-env')()
];
if (options.isProd) {
plugins.push(require('cssnano')({ autoprefixer: false }));
}
return plugins;
};
Solution 2
// rollup.config.js
import svelte from 'rollup-plugin-svelte';
import resolve from 'rollup-plugin-node-resolve';
export default {
input: 'src/main.js',
output: {
file: 'public/bundle.js',
format: 'iife',
},
plugins: [
svelte({
emitCss: false,
css: async (css) => {
css.write('css/svelte-bundle.css');
},
}),
resolve(),
],
};
// package.json
{
//...
"scripts": {
"dev": "npm-run-all --parallel js:watch css:watch",
"js:watch": "rollup -c -w",
"css:watch": "postcss css/app.css --dir dist/ --watch",
},
}
/* css/app.css */
#import 'vars.css';
#import 'mixins.css';
/* all other code ... */
/* and svelte-bundle, which will trigger a bundling with postcss everytime it is emitted */
#import 'svelte-bundle.css';
Conclusion
All in all, I don't like this methods, for exemple because I can't use nesting, as svelte throws an error if the css is not valid.
I would prefer being able to use rollup-plugin-postcss after rollup-plugin-svelte, with emitCss set to false and the possibility to use rollup's this.emitFile in svelte css function, because since once the bundled file is emitted, we should be able to process it.
It seems there are some issues talking about using emitfile, let's hope it will happen sooner than later https://github.com/sveltejs/rollup-plugin-svelte/issues/71
Can't say for sure, but when i compare your setup with mine the most striking difference is that i have:
css: css => {
css.write('public/build/bundle.css');
}
in the svelte options additionally.
My whole svelte option looks like this:
svelte({
preprocess: sveltePreprocess({ postcss: true }),
dev: !production,
css: css => {
css.write('public/build/bundle.css');
}
})
Note, i'm using sveltePreprocess which would make your postcss superfluous, but i don't think that is causing your issue.

Categories

Resources