持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
资产
首先,让我们讨论一下 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 直接当成组件使用
将 svg 直接当成组件使用
将 svg 当作 React 使用,需要开启 svgr 配置,等我们后续介绍到 Umi 配置之后,我们才会真正开启配置,所以以下内容仅仅作为展示,不会出现这节课归档的源码中。
将一个 svg 文件放到 assets
中,如 umi.svg
然后在项目中直接将它当作一个 React 组件使用
import logoImg from '@/assets/logo.png';
// 剩余内容省略
export default () => {
return (
<div>
<img src={LogoImg} width={150} />
</div>
);
}
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 的另一个目的,能够很好的隔离页面的样式,这样不管我们一个项目中有多少个人一起开发,正常样式编写的话,会极少的发生样式污染事件。