问题描述

在打包大的项目时,打包过程中会报错失败。报错信息为 FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory in XXX

首先一定要排除代码中是否有会导致内存泄露的可能,如果没有内存泄露,项目又比较大,打包过程确实消耗较大的内存,那么请继续阅读。

查阅资料后发现,当电脑内存为 8G 时,安装 node,默认分配给堆的内存大小就是 2G,一旦项目运行时超过这个限制就会报错。可以使用如下命令来查看自己的堆大小限制:

node -e 'console.log(v8.getHeapStatistics().heap_size_limit/(1024*1024))'
Read more »

在使用 nginx 存放静态资源时,直接访问不会有问题,但是通过 fetch 去请求资源时,就会触发浏览器跨域限制。如何配置静态资源的 nginx 服务,以避免跨域问题呢?

最简配置

server {
  # 通常不建议在 server 块下直接进行配置,因为 server 块下的 if 块内不支持 add_header,而location块下是支持的。
  location / {
    # 任意 OPTIONS 预检请求,都返回成功
    if ($request_method = 'OPTIONS') {
      # 204表示无返回内容的成功
      return 204;
    }
    # 增加允许跨域主机源的头
    add_header Access-Control-Allow-Origin "*"; # "*" 为任意主机源,生产环境安全起见最好配置为具体的IP或域名
    # 增加允许跨域请求方法的头
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
    # 增加允许跨域请求头字段的头,注意如果有一些自定义增加的头如Authorization等,也要加到这个配置中
    add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization";
  }
}
Read more »

描点跳转

描点跳转的实现非常简单,a 标签 href 属性绑定要跳转的元素 id 即可。

<!-- 跳转按钮 -->
<a href="#foo"></a>

<!-- 被跳转元素应该在一个被溢出的元素中 -->
<div class="overflowed-wrapper">
  <!-- 要跳转到的元素 -->
  <div id="foo"></div>
</div>

过渡动画

过去锚点跳转的过渡动画,常常使用 js 来实现,如今随着浏览器对 css scroll-behavior 属性的全面支持,可以使用该属性来实现平滑过渡动画。

.overflowed-wrapper {
  scroll-behavior: smooth;
}

参考资料 锚点跳转过渡动画

问题描述

声明了一个联合类型,想要将联合类型作为对象的 key,但是报错。

type TestUnionType = "foo" | "bar";

interface TestInterface {
  [index: TestUnionType]: any;
}

// error message
// An index signature parameter type cannot be a union type. Consider using a mapped object type instead.

解决方案

通过报错信息可以看出,联合类型不能作为对象索引签名参数,而应该使用映射对象类型。

type TestUnionType = "foo" | "bar";

interface TestInterface {
  [index in TestUnionType]: any;
}

参考资料

Quick fix for ‘unions can’t be used in index signatures, use a mapped object type instead’

Mapped Types

问题描述

使用环形图,且需要在环中写上自定义的文字,当环形图默认处于居中的位置时,文字位置也使用’center’配置,则可以保证正常居中。

// 环形图默认居中时,自定义文字通过 left: 'center' 也很方便居中
// echarts配置
option = {
  graphic: [
    {
      type: "group",
      left: "center",
      top: "center",
      children: [
        {
          type: "text",
          style: {
            text: "测试居中文字",
            fontSize: 50,
          },
        },
      ],
    },
  ],
  series: [
    {
      type: "pie",
      radius: ["40%", "70%"],
      data: [
        { value: 1048, name: "Search Engine" },
        { value: 735, name: "Direct" },
        { value: 580, name: "Email" },
        { value: 484, name: "Union Ads" },
        { value: 300, name: "Video Ads" },
      ],
    },
  ],
};

而当环形图偏移放置时,自定义文字需要使用百分比定位,此时是文字的左边界定位于设置的百分比位置,而想要实现的效果是文字的中心定位于百分比设置的位置。

如果文字是静态的,还可以硬调整 left 位置,而如果文字是动态的,文字长度不定,硬调整就行不通了,还是需要实现居中效果。

Read more »

简介

命令行语法没有固定的标准,但大家基本都遵循微软的命令行语法

语法

符号 描述
不带括号的文本 必需原样键入的项
<尖括号内的文本> 点位符文本,必需提供值来替换
[中括号内的文本] 可选项
{大括号内的文本} 多个被选项的集合,必需选择一个
分隔线(| 分隔多个互斥(mutually exclusive)被选项,必需选择一个
省略号(... 可以重复和多次使用的项

参考资料

Is there a “standard” format for command line/shell help text?

SVG 是一种矢量图形的图片格式,是 Scalable Vector Graphics(可缩放矢量图形)的缩写。

SVG 的优点:

  • 更小的文件体积,更高的压缩率
  • 可缩放到任意大小,而不会失真(除缩放至很小的尺寸外)
  • 可改变为任何颜色

SVG 的使用方式

作为图片使用

SVG 可以像普通图片那样在 img 标签和 css 的 background 中使用,但是以这种方式使用 SVG 也无法实现对 SVG 的颜色进行修改的操作。

<img src="xxx.svg" alt="xxx" />
<div class="xxx">xxx</div>

<style>
  .xxx {
    width: 100px;
    height: 80px;
    background-image: url(xxx.svg);
  }
</style>
Read more »

在使用 html2canvas 截图时发现 leaflet 中的 geojson 或 polygon 图层在截图后出现偏移。

查阅html2canvas 官方文档看到,html2canvas 对 transform 属性只是有限支持,而在leaflet 官方文档中,初始化地图时的 map-options 中的 renderer 属性规定了矢量图层(vector layer)默认的渲染方式,根据浏览器的支持情况默认选择 svg 与 canvas 两种方式,两种都支持时优先选择 svg 方式。

geojson 的矢量图层,使用 svg 方式在地图上定位就会用到 CSS 的 transform 属性,这也是最终导致 html2canvas 截图漂移的原因。

若将 map-options 中的 renderer 属性固定为 L.Canvas(),则默认使用 canvas 来绘制矢量图层,就避免了使用 svg 标签再通过 transform 属性定位的问题,即可正常截图。

参考资料

html2canvas 官方文档

leaflet 官方文档

Problem taking the screenshot of a Leaflet polygon location

在 javascript 中,我们要给函数表达式增加一个属性,直接如下增加即可:

const myFunction = () => {};
myFunction.prop = "some prop";

在 typescript 中,不定义类型,让函数表达式自动推断类型,仍然可以添加属性,上面的代码仍然不会报错。

但是,如果已经给函数表达式定义了类型,再添加属性就会报错:

const myFunction: () => void = () => {};
myFunction.prop = "some prop"; // Property 'prop' does not exist on type '() => void'.ts(2339)

在 typescript 并不支持在函数表达式中定义属性,如果我们要描述一个带有属性的可调用函数,只需要在对象类型中增加一个调用签名(call signature):

注意 call signature 使用 : 分隔参数与返回值,而函数表达式使用 =>

type MyFunction = {
  prop: string;
  (): void;
};
const myFunction: MyFunction = () => {};
myFunction.prop = "some prop";

// 另外也可以使用 Object.assign() 方法把声明函数与定义属性整合在一起
const myFunction: MyFunction = Object.assign(() => {}, {
  prop: "some prop",
});

参考资料

Call Signatures

Build a function object with properties in TypeScript

封装 fetch

// 请求配置类型,后续可扩展
interface RequestConfig {
  // 基础请求地址
  baseUrl?: string;
  // 超时时间
  timeout?: number;
}

// 请求返回值类型
// 在Promise基础上增加 abortController 属性,可用于手动终止请求
export interface RequestReturn extends Promise<Response> {
  abortController: AbortController;
}

// 重新声明请求类型,在 fetch 默认的 input、init 属性基础上增加了 config 属性,返回值在 Promise 基础上增加了 abortController 属性
interface Request {
  (
    input: RequestInfo,
    init?: RequestInit,
    config?: RequestConfig
  ): RequestReturn;
  create?: any;
}

// 直接调用,该形式类似直接使用 axios
const request: Request = (input, init?, config?) => {
  const controller = new AbortController();
  const signal = controller.signal;
  setTimeout(
    () => {
      controller.abort();
    },
    // 默认10秒超时
    config?.timeout !== null && config?.timeout !== undefined
      ? config?.timeout
      : 10000
  );
  // 由于js只能声明函数,而不能直接声明可调用对象,故使用 Object.assign 的方式将属性与函数整合在一起
  return Object.assign(
    fetch((config?.baseUrl || "") + input, { signal, ...init }),
    { abortController: controller }
  );
};

// 创建实例,该形式类似使用 axios.create 创建实例
request.create = (config: RequestConfig) => {
  const request: Request = (input, init?, instanceConfig?) => {
    const controller = new AbortController();
    const signal = controller.signal;
    setTimeout(() => {
      controller.abort();
    }, instanceConfig?.timeout || config.timeout || 10000);
    return Object.assign(
      fetch((instanceConfig?.baseUrl || config.baseUrl || "") + input, {
        signal,
        ...init,
      }),
      { abortController: controller }
    );
  };
  return request;
};

export default request;
Read more »
0%