背景
想结合tailwindcss
(CSS)和styled-components
(CSS in JS)这两种React中常用的CSS框架,于是有了使用twin这个框架的想法,这篇文章就简单讲一下怎么初始化配置环境。另外会涉及到几个React项目中常见的问题以及解决方法。
快速开始
可以使用已经打包好的Starter:twin_webpack
从零开始
安装CRA和twin
Install Create React App
npm init create-react-app my-app
Install the dependencies
npm install twin.macro tailwindcss styled-components
初始化全局样式
创建文件src/styles/GlobalStyles.js
,并填入以下内容:
// src/styles/GlobalStyles.js
import React from 'react'
import { createGlobalStyle } from 'styled-components'
import tw, { theme, GlobalStyles as BaseStyles } from 'twin.macro'
const CustomStyles = createGlobalStyle`
body {
-webkit-tap-highlight-color: ${theme`colors.purple.500`};
${tw`antialiased`}
}
`
const GlobalStyles = () => (
<>
<BaseStyles />
<CustomStyles />
</>
)
export default GlobalStyles
然后在src/index.js
中引入该全局样式:
// src/index.js
import React from 'react'
import GlobalStyles from './styles/GlobalStyles'
import App from './App'
import { createRoot } from 'react-dom/client'
const container = document.getElementById('root')
const root = createRoot(container)
root.render(
<React.StrictMode>
<GlobalStyles />
<App />
</React.StrictMode>,
)
配置twin
在package.json
中添加以下字段:
// package.json
"babelMacros": {
"twin": {
"preset": "styled-components"
}
},
启用auto css prop feature(2023.4.7更新)
这里是重点,如果少了这一步,则不能在jsx组件中使用
tw="..."和css={[tw`...`, tw`...`]}
这样的特性!!!这个很重要!
安装babel-plugin-styled-components:
npm i -D babel-plugin-styled-components
在项目根目录下创建.babelrc
文件,并添加以下代码:
{
"presets": ["@babel/preset-react"],
"plugins": [
"macros",
"babel-plugin-styled-components"
]
}
到此已经可以开始使用twin.macro的特性了。具体用法可以看一下官方仓库。
配置webpack
如果想用webpack作为打包工具的话,请继续往下看。
安装webpack(我用的版本是5.78.0):
npm install webpack webpack-cli --save-dev
npm install babel-loader @babel/core @babel/preset-env --save-dev
npm install css-loader style-loader --save-dev
创建 Webpack 配置文件。
// 在项目根目录下创建webpack.config.js
// 需要注意的是要把twin用到的插件添加进去
// 另外要配置一下webpack-dev-server
// 此外我还配置了alias和静态资源打包
// 下面是我初始化好的配置
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
// 入口文件
entry: './src/index.js',
// 出口文件
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
],
plugins: [
"babel-plugin-macros", // twin.macro使用
// 其他插件
],
babelrc: true,
},
},
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
use: [
{
loader: 'url-loader', // file-loader
options: {
limit: 8192, // 图片大小限制,超过此大小将被打包成文件
name: '[name].[ext]', // 重命名输出的文件名
outputPath: 'images/', // 输出路径
},
},
],
},
],
},
resolve: {
extensions: ['.js', '.jsx'],
alias: {
"@": path.resolve('src'),
"images": path.resolve('src/assets/images'),
},
},
// 用于指定 webpack-dev-server 的配置
devServer: {
static: path.resolve(__dirname, 'public'),
compress: true,
port: 3000,
open: true,
hot: true,
historyApiFallback:true //缺少该配置,会出现Cannot Get的错误
},
plugins:[
new HtmlWebpackPlugin({
template:path.resolve(__dirname,'public/index.html')
})
]
};
修改项目的 package.json 文件,添加打包脚本。
// 我是在原有的基础上添加了最下面的两个脚本,自己实时调试的话用webpack:dev
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"webpack:build": "webpack",
"webpack:dev": "webpack-dev-server --mode development"
},
到此结束。
alias配置与静态资源打包
alias配置
上面的webpack.config.js
中已经配置好了,当时出了些奇怪的bug,像是由缓存引起的,让我白白调试半天……(~心态爆炸~)
resolve: {
extensions: ['.js', '.jsx'],
alias: {
"@": path.resolve('src'),
"images": path.resolve('src/assets/images'),
},
},
静态资源打包
安装file-loader
和url-loader
(依赖于file-loader):
npm install file-loader --save-dev
npm install url-loader --save-dev
添加配置:
module: {
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
use: [
{
loader: 'url-loader', // file-loader
options: {
limit: 8192, // 图片大小限制,超过此大小将被打包成文件
name: '[name].[ext]', // 重命名输出的文件名
outputPath: 'images/', // 输出路径
},
},
],
},
],
},
创建src/assets/images
目录,并把用到的图片类静态资源放在这里。
之后在CSS中就可以用url(images/XXX.XX)
直接使用图片等静态资源了。(可以根据需要换为其他路径)
其实这里能用这个路径使用图片等静态资源是因为:上面url-loader
这个插件的outputPath
我们设置的是images/
,所以webpack会把打包后的图片放在服务器的/images/XXX这个位置。如下图所示:
此外就是我们设置了 "images": path.resolve('src/assets/images')
的alias,恰巧在本地索引的话也是用"images/XXX"
这个路径,所以IDE这边不会显示这个URL是无效链接。你在css中的url()
中填的是什么路径,浏览器就会在该路径下去请求资源。需要注意的是在以上的配置环境下,css中不能用alias。就是你字面上写的是什么URL,到时候请求的就是服务器根路径/URL
这个URL。所以我让url-loader
把打包后的资源放在和这个“同名”的images/
路径下。
但是我这里还是有点小问题,就是只在CSS中使用某个静态资源的时候,webpack不能发现并打包,需要手动import以下这个资源才行。使用的时候需要注意了。
2023.4.11补充
用Webpack打包的话,/dist/index.html中的图标静态资源的路径需要改一下。举个例子:
假如我项目的首页路径是https://qiuyedx.github.io/NavPage
,静态资源被打包到/images
路径下,那么路径应改为/NavPage/images/XXX.ico
。
Comments NOTHING