我正在为 npm 开发一个 React 组件库。技术堆栈包括:
反应 打字稿 样式组件 我在构建过程中使用 Babel 和 Rollup。
我的问题是我想在我的组件中使用 css prop,但它没有按预期转换为样式。使用像
const StyledSpan = styled.span
这样的包装器可以正常工作,但我需要一个也可以转换 css 属性的解决方案。
如果我在我的应用程序中使用 cssprop,它也可以正常工作,因为在底层,Babel 插件会将任何具有 css prop 的元素转换为样式组件。但 rollup 和 babel 却没有做到这一点。 :(
组件:
import React from 'react';
import { css } from 'styled-components';
const Text= () => (
<span
css={css`
background-color: orange;
color: red;
`}
>
Bob
</span>
);
export default Text;
汇总配置:
import { readFileSync } from 'fs';
import { defineConfig } from 'rollup';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';
import external from 'rollup-plugin-peer-deps-external';
import postcss from 'rollup-plugin-postcss';
import typescriptEngine from 'typescript';
import babel from '@rollup/plugin-babel';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
const packageJson = JSON.parse(readFileSync('./package.json'));
export default defineConfig({
input: './src/index.ts',
output: [
{
file: packageJson.main,
format: 'cjs',
sourcemap: true,
exports: 'named',
name: packageJson.name,
interop: 'compat',
},
{
file: packageJson.module,
format: 'esm',
exports: 'named',
sourcemap: true,
interop: 'compat',
},
],
plugins: [
peerDepsExternal(),
postcss({
plugins: ['babel-plugin-styled-components'],
minimize: true,
}),
babel({
babelHelpers: 'runtime',
plugins: [
[
'babel-plugin-styled-components',
{
namespace: 'react-ui',
displayName: true,
fileName: true,
transpileTemplateLiterals: true,
ssr: false,
},
"@babel/plugin-transform-runtime"
],
],
presets: ['react-app', '@babel/preset-react', '@babel/preset-typescript'],
extensions: ['.js', '.jsx', '.ts', '.tsx'],
}),
external({ includeDependencies: true }),
resolve({ browser: true }),
commonjs({
include: 'node_modules/**',
}),
typescript({
tsconfig: './tsconfig.json',
typescript: typescriptEngine,
sourceMap: true,
exclude: [
'coverage',
'.storybook',
'storybook-static',
'config',
'dist',
'node_modules/**',
'*.cjs',
'*.mjs',
'**/__snapshots__/*',
'**/__tests__',
'**/*.test.js+(|x)',
'**/*.test.ts+(|x)',
'**/*.mdx',
'**/*.story.ts+(|x)',
'**/*.story.js+(|x)',
'**/*.stories.ts+(|x)',
'**/*.stories.js+(|x)',
'setupTests.ts',
'vitest.config.ts',
],
}),
],
external: ['styled-components'],
});
打字稿配置:
{
"compilerOptions": {
"declaration": true,
"declarationDir": "./types",
"strict": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"noUnusedParameters": true,
"strictNullChecks": true,
"moduleResolution": "node",
"noImplicitAny": true,
"outDir": "./prebuild",
"target": "es5",
"jsx": "react"
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
package.json
{
"name": "react-component-library",
"version": "1.0.0",
"description": "npm package with",
"main": "dist/index.js",
"module": "dist/index.esm.js",
"types": "dist/index.d.ts",
"scripts": {
"rollup": "rimraf dist && rollup -c --bundleConfigAsCjs",
"prepair": "rimraf dist && rimraf prebuild && rimraf lib",
"build": "tsc && cross-env NODE_ENV=development babel ./prebuild --out-dir lib && cross-env NODE_ENV=development rollup -c --bundleConfigAsCjs"
},
"files": [
"dist"
],
"author": "",
"license": "ISC",
"dependencies": {
"@babel/plugin-transform-runtime": "^7.24.7",
"@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7",
"@babel/runtime": "^7.25.0",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^26.0.1",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.6",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/styled-components": "^5.1.34",
"@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.19",
"babel-loader": "^9.1.3",
"babel-plugin-css-prop": "^0.1.0",
"babel-plugin-macros": "^3.1.0",
"babel-plugin-styled-components": "^2.1.4",
"babel-preset-react-app": "^10.0.1",
"cross-env": "^7.0.3",
"postcss": "^8.4.40",
"postcss-loader": "^8.1.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"rimraf": "^6.0.1",
"rollup": "^4.19.0",
"rollup-plugin-peer-deps-external": "^2.2.4",
"rollup-plugin-postcss": "^4.0.2",
"rollup-plugin-typescript2": "^0.36.0",
"styled-components": "^6.1.12",
"ts-loader": "^9.5.1",
"typescript": "^5.5.4",
"typescript-plugin-styled-components": "^3.0.0"
},
"devDependencies": {
"@babel/cli": "^7.24.8",
"@babel/core": "^7.24.9",
"@babel/preset-env": "^7.25.0",
"rollup-plugin-dts": "^6.1.1"
},
"peerDependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1",
"styled-components": "^6.1.12"
}
}
如果我将组件更改为样式包装器,它就会起作用,如下所示: 但我不想申请这个表格
import React from 'react';
import styled from 'styled-components';
export const StyledSpan = styled.span`
background-color: orange;
color: blue;
`;
const Text = () => (
<StyledSpan>
Bob
</StyledSpan>
);
export default Text;
我的解决方案是parcelJs。 Rollup 无法正确完成这项工作,但 Parcel 有帮助。 申请起来更加容易。它通过您的应用程序/组件库检测应该安装哪些额外的依赖项。相当不错的东西。