4.6.7 • Published 8 months ago

@cara/porter v4.6.7

Weekly downloads
5
License
BSD-3-Clause
Repository
github
Last release
8 months ago

Porter

NPM Downloads NPM Version codecov

中文版

Porter 是一个前端打包构建工具,支持开发者使用 CommonJS 或者 ES Modules 开发 Web 应用,支持如下特性:

  1. 支持同步或者异步的模块加载方式,可以任意使用 require()require.async()import、或者 import() 来加载模块,异步加载的模块会自动拆成单独的包;
  2. 与 NPM 包基本对应,可以选择按包构建,也可以选择全部合并代码到同步或者异步加载的入口模块;
  3. 足够快的依赖解析与编译性能,合理利用编译缓存,生产环境构建性能更易优化。

推荐阅读《快速上手》和《帮助手册》。

基础配置

文本主要介绍 @cara/porter 中间件的用法,如果要了解 @cara/porter-cli,可以访问对应的 NPM 包,或者阅读 Porter 帮助手册

Porter 提供 Egg、Koa、和 Express 不同格式的中间件:

const Koa = require('koa')
const Porter = require('@cara/porter')

const app = new Koa()
const porter = new Porter()
app.use(porter.async())

// express
app.use(porter.func())

Modules

以下面这个目录结构为例,默认可以将前端代码放在 ./components 目录:

➜  examples/cli git:(master) tree -L 2
.
├── components        # browser modules
│   ├── app.css
│   └── app.js
├── node_modules      # dependencies
│   ├── @cara
│   │   └── porter
│   ├── jquery
│   └── prismjs
├── package.json
└── public
    └── index.html    # homepage

然后在 ./public/index.html 引用:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>A Porter Demo</title>
  <!-- CSS 入口模块 -->
  <link rel="stylesheet" type="text/css" href="/app.css">
</head>
<body>
  <h1>A Porter Demo</h1>
  <!-- JavaScript 入口模块 -->
  <script src="/app.js?main"></script>
</body>
</html>

JavaScript 入口模块有个额外的 ?main 参数,原先有这个是为了告诉 Porter 在打包入口模块时是否把模块加载器 loader.js 包含进去。相应的,下面这两种写法不会包含 loader.js:

<!-- entry format 1 -->
<script src="/loader.js" data-main="app.js"></script>
<!-- entry format 2 -->
<script src="/loader.js"></script>
<script>porter.import('app')</script>

上述写法都不再推荐,直接写 <script src="/app.js?main"></script> 就好。

在 JavaScript 代码中,下面这些写法都是支持的,可以加载 NPM 包、CSS、WebAssembly、或者 Web Worker:

import $ from 'jquery';         // => ./node_modules/jquery/dist/jquery.js
import * as React from 'react'; // => ./node_modules/react/index.js
import util from './util';      // => ./components/util.js or ./components/util/index.js

// <link rel="stylesheet" type="text/css" href="/app.js"> is still needed though
import './foo.css';

// will fetch the wasm file, instantiate it, and return the exports
import wasm from './foo.wasm';

// will bundle and fetch worker.js separately
import Worker from 'worker-loader!./worker.js';

在 CSS 入口模块中,同样支持 @import,并且会在打包阶段处理,将相关内容按照引用顺序合并到一起:

@import "prismjs/themes/prism.css";
@import "./base.css";

如果没有编写专门的 CSS 入口模块,但是在 JavaScript 入口模块中又有 import './foo.css';,Porter 也会生成对应的 CSS 输出文件,这个处理逻辑与 webpack 的 mini-css-extract-plugin 相仿。默认情况下,此时打包的 app.js 不会自动加载 app.css,需要在 HTML 页面中自行引入。

配置项

下面是 Porter 支持的配置项列表:

const path = require('path');
const Porter = require('@cara/porter');

const porter = new Porter({
  // project root, defaults to `process.cwd()`
  root: process.cwd(),

  // paths of browser modules, or components, defaults to `'components'`
  paths: 'components',

  // output settings
  output: {
    // path of the compile output, defaults to `'public'`
    path: 'public',
  },

  // cache settings
  cache: {
    // path of the cache store, defaults to `output.path`
    path: '.porter-cache',

    // cache identifier to shortcut cache invalidation
    identifier({ packet }) {
      return JSON.stringify([
        require('@cara/porter/package.json').version,
        packet.transpiler,
        packet.transpilerVersion,
        packet.transpilerOpts,
      ]);
    },
  },

  // preload common dependencies, defaults to `[]`
  preload: [ 'preload', '@babel/runtime' ],

  // the module resolution behaviour
  resolve: {
    // an alias at project level to simplify import specifier, such as
    //     import util from '@/util'; // => components/util/index.js
    alias: {
      '@': path.join(process.cwd(), 'components'),
    },

    // supported extensions
    extensions: [ '*', '.js', '.jsx', '.ts', '.tsx', '.css' ],

    // transform big libraries that support partial import by conventions
    import: [
      { libraryName: 'antd', style: 'css' },
      { libraryName: 'lodash',
        libraryDirectory: '',
        camel2DashComponentName: false },
    ],
  },

  // transpile settings
  transpile: {
    // turn on transpilation on certain dependencies, defaults to `[]`
    include: [ 'antd' ],
  },

  // bundle settings
  bundle: {
    // excluded dependencies will be bundled separately, defaults to `[]`
    exclude: [ 'antd' ],
  },

  // source settings
  source: {
    // serve the source file if it's development mode, defaults to `false`
    serve: process.env.NODE_ENV !== 'production',

    // the `sourceRoot` in the generated source map, defaults to `'/'`
    root: 'localhost:3000',
  },
});

构建部署

前端代码经过构建部署之后,生产环境就不需要依赖打包构建工具了。可以使用 porter.compileAll({ entries }) 方法来执行构建:

const porter = new Porter({
  output: { path: 'dist' },
});

await porter.compileAll({
  entries: ['app.js', 'app.css']
});

Porter 会解析入口模块相关依赖,按照下面的打包逻辑输出构建产物:

  • Entries are bundled separately, e.g. entries: ['app.js', 'app2.js'] are compiled into two different bundles.
  • Dependencies are bundled per package with internal modules put together, e.g. jQuery gets compiled as jquery/3.3.1/dist/jquery.4f8208b0.js.
  • Dependencies with multiple entries gets bundled per package as well, e.g. lodash methods will be compiled as lodash/4.17.10/lodash.36bdcd6d.js.

  • 入口模块会分别打包,例如 entries: ['app.js', 'app2.js'] 会分别打包成两个文件;

  • 默认按照 NPM 包打包依赖,包内部的模块会被打包到一起,例如 jQuery 包含的模块会被打包到 jquery/3.3.1/dist/jquery.4f8208b0.js
  • 如果 NPM 包有多个入口模块被引用,会被打包到一起,页面动态加载的时候也只会加载这个包的同一个构建产物,例如 app.js 引用 lodash/throttle、app2.js 引用 lodash/debounce,最终打包的是 lodash/4.17.10/lodash.36bdcd6d.js,两个页面都会加载这个构建产物。

以下面这个入口模块为例:

import $ from 'jquery';
import throttle from 'lodash/throttle';
import camelize from 'lodash/camelize';
import util from './util';
// code

调用 porter.compileAll({ entries: ['app.js'] }) 完成后,输出的文件大致如下:

public
├── app.${contenthash}.js
├── app.${contenthash}.js.map
├── jquery
│   └── 3.3.1
│       └── dist
|           ├── jquery.${contenthash}.js
|           └── jquery.${contenthash}.js.map
└── lodash
    └── 4.17.10
        ├── ~bundle.${contenthash}.js
        └── ~bundle.${contenthash}.js.map

也可以选择全部打包到一起,这样只会按照入口模块来输出构建产物:

// default
porter.compileEntry('app.js', { package: true })

// bundle everything
porter.compileEntry('app.js', { all: true })

也可以抽取一些公共包,使用 options.preload 或者 options.bundle.exclude 配置都可以实现,详细参考 Porter 配置文档

4.6.7

8 months ago

4.6.6

11 months ago

4.6.3

11 months ago

4.6.2

11 months ago

4.6.5

11 months ago

4.6.4

11 months ago

4.6.0-alpha.1

1 year ago

4.6.0-alpha.0

1 year ago

4.6.1

1 year ago

4.6.0

1 year ago

4.5.2

1 year ago

4.5.0

1 year ago

4.5.1

1 year ago

4.4.7

1 year ago

4.4.3

1 year ago

4.4.5

1 year ago

4.4.4

1 year ago

4.4.6

1 year ago

4.4.1

1 year ago

4.4.0

1 year ago

4.4.2

1 year ago

4.3.2

2 years ago

4.3.1

2 years ago

4.3.4

2 years ago

4.3.3

2 years ago

4.3.0

2 years ago

4.2.12

2 years ago

4.2.13

2 years ago

4.2.14

2 years ago

4.2.10

2 years ago

4.2.11

2 years ago

4.2.3

2 years ago

4.2.2

2 years ago

4.2.5

2 years ago

4.2.4

2 years ago

4.2.1

2 years ago

4.2.0

2 years ago

4.2.7

2 years ago

4.2.6

2 years ago

4.2.9

2 years ago

4.2.8

2 years ago

4.0.9

2 years ago

4.0.10

2 years ago

4.0.12

2 years ago

4.0.11

2 years ago

4.0.13

2 years ago

4.1.0

2 years ago

4.1.1

2 years ago

4.0.5

2 years ago

4.0.4

2 years ago

4.0.7

2 years ago

4.0.6

2 years ago

4.0.1

2 years ago

4.0.3

2 years ago

4.0.2

2 years ago

4.0.8

2 years ago

4.0.0

2 years ago

4.0.0-alpha.9

2 years ago

4.0.0-alpha.7

2 years ago

4.0.0-alpha.8

2 years ago

4.0.0-alpha.5

2 years ago

4.0.0-alpha.6

2 years ago

4.0.0-alpha.15

2 years ago

4.0.0-alpha.14

2 years ago

4.0.0-alpha.4

2 years ago

4.0.0-alpha.13

2 years ago

4.0.0-alpha.12

2 years ago

4.0.0-alpha.11

2 years ago

4.0.0-alpha.10

2 years ago

4.0.0-beta.15

2 years ago

4.0.0-beta.14

2 years ago

4.0.0-beta.17

2 years ago

4.0.0-beta.16

2 years ago

4.0.0-beta.11

2 years ago

4.0.0-beta.10

2 years ago

4.0.0-beta.13

2 years ago

4.0.0-beta.12

2 years ago

4.0.0-beta.18

2 years ago

4.0.0-beta.8

2 years ago

4.0.0-beta.7

2 years ago

4.0.0-beta.6

2 years ago

4.0.0-beta.5

2 years ago

4.0.0-beta.4

2 years ago

4.0.0-beta.3

2 years ago

4.0.0-beta.2

2 years ago

4.0.0-beta.1

2 years ago

4.0.0-beta.0

2 years ago

4.0.0-beta.9

2 years ago

4.0.0-alpha.3

2 years ago

4.0.0-alpha.1

2 years ago

4.0.0-alpha.2

2 years ago

4.0.0-alpha.0

2 years ago

3.3.1

2 years ago

3.3.0

3 years ago

3.3.3

2 years ago

3.3.2

2 years ago

3.2.6

3 years ago

3.2.5

3 years ago

3.2.4

3 years ago

3.2.3

3 years ago

3.2.2

3 years ago

3.2.1

3 years ago

3.2.0

4 years ago

3.1.5

4 years ago

3.1.4

4 years ago

3.2.0-0

4 years ago

3.1.3

4 years ago

3.1.2

4 years ago

3.1.0

5 years ago

3.0.6

5 years ago

3.0.5

5 years ago

3.0.4

5 years ago

3.0.3

5 years ago

3.0.2

5 years ago

3.0.1

5 years ago

3.0.0

6 years ago

2.2.0

6 years ago

2.1.4

6 years ago

2.1.3

6 years ago

2.1.2

6 years ago

2.1.1

6 years ago

2.1.0

6 years ago

2.0.2

6 years ago

2.0.1

6 years ago

2.0.0

6 years ago

2.0.0-12

6 years ago

2.0.0-11

6 years ago

2.0.0-10

6 years ago

2.0.0-9

6 years ago

2.0.0-8

6 years ago

2.0.0-7

6 years ago

2.0.0-6

6 years ago

2.0.0-5

6 years ago

2.0.0-4

6 years ago

1.0.6

6 years ago

1.0.5

6 years ago

1.0.4

6 years ago

1.0.3

6 years ago

2.0.0-3

6 years ago

2.0.0-2

6 years ago

2.0.0-1

6 years ago

2.0.0-0

6 years ago

1.0.2

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago

1.0.0-alpha.7

6 years ago

1.0.0-alpha.6

6 years ago

1.0.0-alpha.5

6 years ago

1.0.0-alpha.4

6 years ago

1.0.0-alpha.3

6 years ago

1.0.0-alpha.2

6 years ago

1.0.0-alpha.1

6 years ago