资产
首先,让我们讨论一下 Umi 如何处理 静态资产 (如图像)。
新建文件夹 src/assets
,值得注意的是,这并不是一个“约定目录”,仅仅是一个建议目录,我们希望能有一个目录统一管理我们的静态资源。
将https://umijs.org/
官网的 Umi logo 图片下载下来,放到这个文件夹下,即 src/assets/logo.pg
。
在组件中使用图片,我们可以将它当作一个模块直接引入,比如我们在 index
页面中使用它:
import logoImg from '@/assets/logo.png'; // 剩余内容省略 export default () => { return ( <div> <img src={LogoImg} width={150} /> </div> ); } 复制代码
Umi 默认将 @
映射到项目的 src
目录中,所以你可以在项目的任意位置使用 @/component
或 @/utils
之类的路径来引入模块和方法类。你将不再需要使用到如 ../../../componet
之类的相对路径。
在 css 中同样支持别名,只是别忘了在 css 中使用别名需要增加 ~
前缀。
.logo { background: url(~@/foo.png); } 复制代码
通过路径引入图片的时候,如果图片小于 10K,会被编译为 Base64,否则会被构建为独立的图片文件输出到构建目录的 static
目录中。
10K 这个阈值可以通过 inlineLimit 配置修改。如:
{ inlineLimit: 10000; // 10K } 复制代码
如果你有一些希望原样被拷贝到构建目录的文件,如 robots.txt
、Google 站点验证和其他任何静态资产希望被拷贝到构建目录中,则可以将他们放置在顶层的 public
目录中。
注意:不能存在
public/index.html
和其他任何与构建产物同名的文件,不然构建产物将会被覆盖,导致不可预知的错误。
修复资产类型错误
引入 import logoImg from '@/assets/logo.png';
之后,会有一个类型错误,这是因为 typescript 无法识别 png 后缀的文件名。因此我们可以在项目中添加一个 typings.d.ts
来修复这些不是别的文件后缀。当然如果有些库,你真的无法找到它对应的 types 库,那你也可以在这个文件中定义它或者忽略它。
declare module '*.css'; declare module '*.less'; declare module '*.scss'; declare module '*.sass'; declare module '*.svg'; declare module '*.png'; declare module '*.jpg'; declare module '*.jpeg'; declare module '*.gif'; declare module '*.bmp'; declare module '*.tiff'; declare module '*.json'; 复制代码
将 svg 直接当成组件使用
CSS 样式
接下来我们来聊一聊 CSS 样式。 打开我们首页的代码,即 src/pages/index
。
import React from "react"; import { Link, useSearchParams, createSearchParams, useLocation, } from "umi"; import logoImg from '@/assets/logo.png'; // 需要开启 svgr 配置之后才可用 // import UmiLogo from '@/assets/umi.svg'; export default () => { const [searchParams, setSearchParams] = useSearchParams(); const location = useLocation(); console.log(location); const a = searchParams.get("a"); const b = searchParams.get("b"); return ( <div> Index Page <img src={logoImg} width={150}/> {/* <UmiLogo/> */} <p> <Link to="/user">Go to user page</Link> </p> <p> SearchParams ---- a:{a};b:{b} </p> <p>State ---- {JSON.stringify(location?.state)}</p> <button onClick={() => { setSearchParams(createSearchParams({ a: "123", b: "456" })); }} > Change SearchParams </button> </div> ); }; 复制代码
如你所见,我们在首页编写了 html 的 demo。你可以理解为我们搭建了页面的‘骨架’。但是往往我们需要页面按照我们的设计来呈现样式,因此我们还需要加上 CSS 样式,来声明 html 标签的渲染样式。
编写和导入 CSS
Umi 内置支持 CSS 和 Less 的支持,允许你导入 .css
和 .less
文件 。
新建一个 src/pages/index.less
文件:
.main{ font-size: 35px; } 复制代码
在首页中引入 import "./index.less"
这样我们就可以在页面中使用我们定义好的样式了
import './index.less'; // 剩余内容省略 export default () => { return ( <div className="main"> </div> ); } 复制代码
运行 umi dev
,访问页面,你将会看到首页的 font-size
变成 35px
。
auto CSS Modules
一般我们在别的框架中使用 CSS Modules 是要引入如 index.module.less
之类的文件,Umi 则通过 babel 插件来实现,只要引用 index.less
就会自动使用 CSS Modules。
我们使用 CSS Modules 的方式在 user
页面中使用样式
import styles from './index.less'; // 剩余内容省略 export default () => { return ( <div className={styles.main}> </div> ); } 复制代码
通过浏览器开发者工具查看页面 dom ,你可以找到 user 页面的 div 的 class 的类名是如 main___us1GC
这样的带有一个随机 哈希值的类名。(index 页面中则是 main
)
所以这个也是我们使用 CSS Modules 的另一个目的,能够很好的隔离页面的样式,这样不管我们一个项目中有多少个人一起开发,正常样式编写的话,会极少的发生样式污染事件。