🐠 转换(Transforms)

许多打包工具需要你安装和配置插件来转换资源,Parcel 支持许多开箱即用的转换器和内置的编译器。您可以使用 Babel 转换 JavaScript ,使用 PostCSS 转换 CSS ,使用 PostHTML 转换 HTML。Parcel 在模块中找到配置文件 (例如 .babelrc, .postcssrc) 时会自动运行并进行转换。

这甚至可以在第三方 node_modules 中运行: 如果配置文件作为程序包的一部分发布,则仅为该模块自动启用转换。由于只需要处理需要转换的模块,因此可以快速打包。这也意味着你不需要手动配置转换,使其包含和排除某些文件,也不需要知道如何构建第三方代码,以便在你的应用程序中使用它。

Babel

Babel 是一个流行的 JavaScript 转换器,拥有大型的插件生态系统。Babel 与 Parcel 一起使用的方式与单独使用或与其他打包工具一起使用的方式相同。

在你的应用程序中安装 presets 和 plugins :

yarn add babel-preset-react

接着, 创建一个 .babelrc:

{
  "presets": [
    "react"
  ]
}

Default babel transforms

Parcel transpiles your code with babel-preset-env by default, this is to transpile every module both internal (local requires) and external (node_modules) to match the defined target.

For the browser target it utilises browserlist, the target browserlist can be defined in package.json (engines.browsers or browserslist) or using a configuration file (browserslist or .browserslistrc).

The browserlist target defaults to: > 0.25% (Meaning, support every browser that has 0.25% or more of the total amount of active web users)

For the node target, Parcel uses the engines.node defined in package.json, this default to node 8.

PostCSS

PostCSS 是一个使用插件转换 CSS 的工具, 例如 autoprefixercssnext 以及 CSS Modules 。你可以使用这些名称之一创建配置,从而达到使用 Parcel 配置 PostCSS 的目的: .postcssrc (JSON),.postcssrc.js, 或 postcss.config.js.

在你应用程序中安装 plugins:

yarn add postcss-modules autoprefixer

接着,创建一个 .postcssrc 文件:

{
  "modules": true,
  "plugins": {
    "autoprefixer": {
      "grid": true
    }
  }
}

Plugins 在 plugins 对象中被指定为 key,并使用对象的值定义选项。如果插件没有选项,只需将其设置为 true 即可。

可以在 .browserslistrc 中指定 autoprefixer、cssnext 和目标浏览器的其他工具:

> 1%
last 2 versions

使用顶级 modules 键时,CSS 模块启用方式稍有不同。这是因为 Parcel 需要对 CSS 模块提供特殊支持,因为它们也导出一个包含在 JavaScript 包中的对象。请注意,你仍然需要在你的项目中安装 postcss-modules

与现有的 CSS 库一起使用

为了使 CSS 模块能够与现有模块一起正常工作,需要在模块自己的 .postcssrc 中指定这种支持。

设置 cssnano 压缩(minify)配置

Parcel 将 cssnano 添加到 postcss 中以便在生产模式中构建并压缩(minify) CSS。通过创建一个 cssnano.config.js 文件可以添加自定义配置:

module.exports = {
  preset: ['default', {
    calc: false,
    discardComments: {
      removeAll: true,
    }
  }]
};

PostHTML

PostHTML 是一个通过插件转换 HTML 的工具。你可以使用这些名称之一创建配置,从而达到使用 Parcel 配置 PostHTML 的目的: .posthtmlrc (JSON) ,posthtmlrc.js ,或者 posthtml.config.js

在你的应用程序中安装 plugin:

yarn add posthtml-img-autosize

接着,创建一个 .posthtmlrc:

{
  "plugins": {
    "posthtml-img-autosize": {
      "root": "./images"
    }
  }
}

插件名在 plugins 对象中被指定为 key,并且参数使用对象值定义。如果插件没有参数,只需将其设置为 true 即可。

TypeScript

TypeScript 是 JavaScript 的超集,并且支持类型检查,它可以编译成普通的 JavaScript,同时也支持现代 ES2015+ 的特性。转换 TypeScript 无需任何额外配置,开箱即用。

<!-- index.html -->
<html>
<body>
  <script src="./index.ts"></script>
</body>
</html>
// index.ts
import message from "./message";
console.log(message);
// message.ts
export default "Hello, world";

ReasonML/BuckleScript

ReasonML 利用 BuckleScript 把 OCaml 编译为可执行的 JavaScript。通过安装相应的依赖并创建 bsconfig.json 配置文件即可使用 ReasonML :

$ yarn add bs-platform --dev
// bsconfig.json
// from https://github.com/BuckleScript/bucklescript/blob/master/jscomp/bsb/templates/basic-reason/bsconfig.json

{
  "name": "whatever",
  "sources": {
    "dir": "src",
    "subdirs": true
  },
  "package-specs": {
    "module": "commonjs",
    "in-source": true
  },
  "suffix": ".bs.js",
  "bs-dependencies": [
  ],
  "warnings": {
    "error": "+101"
  },
  "namespace": true,
  "refmt": 3
}
<!-- index.html -->
<!doctype html>
<html>
<body>
  <script src="./src/index.re"></script>
</body>
</html>
/* src/index.re */
print_endline("Hello World");

ReasonReact

ReasonReact 使针对 ReasonML 的 React 绑定(binding)。Parcel 也对其提供了支持:

$ yarn add react react-dom reason-react
// bsconfig.json

{
  "name": "whatever",
+ "reason": {
+   "react-jsx": 2
+ },
  "sources": {
    "dir": "src",
    "subdirs": true
  },
  "package-specs": {
    "module": "commonjs",
    "in-source": true
  },
  "suffix": ".bs.js",
  "bs-dependencies": [
+   "reason-react"
  ],
  "warnings": {
    "error": "+101"
  },
  "namespace": true,
  "refmt": 3
}
<!-- index.html -->
<html>
<body>
+  <div id="app"></div>
  <script src="./src/index.re"></script>
</body>
</html>
/* src/Greeting.re */

let component = ReasonReact.statelessComponent("Greeting");

let make = (~name, _children) => {
  ...component,
  render: _self => <div> (ReasonReact.string("Hello! " ++ name)) </div>,
};
/* src/index.re */

ReactDOMRe.renderToElementWithId(<Greeting name="Parcel" />, "app");