we-pepper v2.0.21
Pepper
pepper 是一个基于 webpack 的打包工具,不依赖于具体项目,相反,它是诸多 RWE ( React & Webpack & ES6 ) 项目共同点的抽离。对 RWE 项目来说,开发环境和部署环境都是通用的,他们存在的唯一目的,就是方便代码的调试和打包。这就是 pepper 诞生的初衷。
现在,只需在RWE 项目的根目录下创建 pepepr.config.js
( pepper 的配置文件),就可具备初始 RWE 项目的所有功能。
关于 Yarn
pepper 可以通过 yarn 进行安装
// firstly: install yarn, may require your sudo privilege
npm install yarn -g;
// then install depends packages
yarn install;
// link and compile pepper
npm link;
// then you are done! enjoy pepper ;)
如何安装
gitlab 手动编译
# 克隆 pepper 仓库到本地目录(默认 pepper 即可) git clone git@gitlab.intra.wepiao.com:FEI/pepper.git # 进入 pepper 目录 cd pepper # 安装运行时依赖 & 编译 npm link
npm 全局 ( depreacted & outdated) 此种方式后续会逐渐废弃
npm install we-pepper -g --registery http://npm.intra.wepiao.com
项目创建
cli 命令 | 说明 |
---|---|
pepper init name | es6 & react-router |
pepper init-redux name | es6 & react-router & redux |
pepper init-rn name | react-native (演出票 DEMO) |
目录结构一览
.
├── /dist/ # 代码打包目录
├── /node_modules/ # node依赖包
├── /src/ # 源码目录
│ ├── /pages/ # 页面
│ ├── /components/ # 公用组件
│ ├── /assets/ # 图片、字体资源
│ ├── /scss/ # 公用样式
│ └── /utils/ # 公用JS模块
├── pepper.config.js # pepper的配置文件
├── index.template.html # 首页HTML模版, 可选
└── package.json # 这个就不用说了吧
项目打包
cli 命令 | 说明 |
---|---|
pepper start -p PORT | 本地调试,基于 start 配置 |
pepper test | 运行测试代码, 基于 test 配置打包 |
pepper pre | 基于 pre 配置打包,压缩 |
pepper release | 基于 release 配置打包,压缩,移除 console 日志 |
pepper library mode | 基于现有配置文件,将代码打包成 lib 库,可发布至 npm ,供其他项目使用, 使用参考 |
打包结果一览
➜ pepper pre
Hash: d72ff25390f520660578
Version: webpack 1.12.11
Time: 8205ms
Asset Size Chunks Chunk Names
js/shared-9f5500d8.js 34.7 kB 0, 3 [emitted] shared
js/home-1fb4ec5e.js 6.85 kB 1, 3 [emitted] home
js/vendor-5a9e0e26.js 131 kB 2, 3 [emitted] vendor
index.html 647 bytes [emitted]
[0] multi vendor 40 bytes {2} [built]
+ 194 hidden modules
项目测试
基于模块 | 说明 |
---|---|
ava | 🚀 Futuristic JavaScript test runner |
enzyme | JavaScript Testing utilities for React |
测试功能正在开发中
配置文件
配置项 | 默认值 | 说明 | |
---|---|---|---|
host | 0.0.0.0 | 调试IP,本地调试使用默认值即可 | |
port | 9527 | 端口,start 模式下,可通过 -p [PORT] 覆盖该项 | |
base | src | 代码根目录 | |
externals | {} | demo { '$': 'jQuery' } | |
jshash | true | 是否启用 js 文件名字添加 hash 后缀 | |
build | dist | 打包目录,打包后的代码将放置到此处,与 base 同级 | |
static | 见示例配置 | 静态资源 CDN 域名设置,路径结尾包含/ 代码中以 STATIC 引用, etc.. console.log(STATIC) | |
api | 见示例配置 | API 路径设置,路径结尾不包含/ 代码中以 API 引用 | |
globals | 见示例配置 | 更多全局变量设置,js代码中以配置项 key 的大写 KEY 形式引用,如果在首页模板中,用法则为{%=o.configs.KEY%} | |
vendor | 'react', 'react-dom' | 将指定的类库打包到 vendor-hash.js中,建议常用的类库放到此处。此项不包含业务代码,不会经常变动此项,可充分利用缓存优势 | |
alias | 见示例配置 | 1) 路径别名 2) 模块化引用方式,去相对路径痛点 | |
alias_modules | 见示例配置 | 模块别名 , 比如使用 react-lite 替换 react | |
devtool | source-map | 参见 webpack 调试选项 | |
template | 见示例配置 | html 模版配置 | |
template.title: | 模版 document.title | ||
template.keywords | 模版 meta keywords , 默认为空 | ||
template.description | 模版 meta description , 默认为空 | ||
template.viewport | width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no | 模版 meta viewport | viewport 配置 |
template.favicon | 模版 favicon , 默认为空 | ||
template.path: | 设定自定义模版的的路径,会替换默认模版,可选。 有语法要求 | ||
pages | pages | 程序入口,页面目录,默认为 pages/index ,可修改, 支持多 html 模版,详细见示例配置 | |
scss | scss | 公共样式目录,可修改 | |
assets | assets | 静态资源目录,可修改 | |
components | components | 页面间共享的组件目录,可修改(非共用组件,放置在当前页面目录即可) | |
eslint | false | 是否启用 eslint , 默认关闭,如果启用该选项,请在项目根目录提供自己的 .eslintrc | |
css_modules | false | 是否启用 CSS Modules, 默认关闭 | |
esmode | es6 | 模版代码风格,支持 es5 和 es6 , 默认为 es6 , 兼容 `es7 | |
transfer_assets | false | 打包时是否 copy asset 目录,默认 false | |
base64_image_limit | 1024 | 对所有小于该大小的图片启用 base64 转码, 默认 10240 (10k) | |
transfer_assets | false | 打包时是否 copy asset 目录,默认 false |
示例配置
{
"host": "0.0.0.0",
"port": "9527",
"base": "src",
"build": "dist",
"static": { // CDN domain, or just leave it blank if not using
"start": "/",
"test": "/",
"pre": "/",
"release": "/"
},
"globals": { // 配置全局变量,这里配置了 static_api 和 api 两个全局变量
// static api
"static_api": {
"start": "", // local api base entry
"test": "",
"pre": "", // online api base entry
"release": ""
},
"api": {
"start": "",
"test": "",
"pre": "",
"release": ""
}
},
"vendor": ["react", "react-dom"],
"alias": {
"wepiao": "components",
"scss": "scss"
},
"alias_modules": {
"react": "react-lite",
"react-dom": "react-lite"
},
"devtool": "source-map",
"template": {
"path": "index.template.html", //使用自定义模版
"title": "",
"keywords": "",
"description": "",
"viewport": "",
"favicon": "assets/images/favicon.ico"
},
"pages": "pages",
/* // multiple template config
*
* pages: {
* index: { entry: 'pages/index', template: 'index.template.html' },
* other: { entry: 'pages/other', template: 'other.template.html' }
* }
*/
"scss": "scss",
"components": "components",
"assets": "assets",
"eslint": false, // 如果启用该选项,请在项目根目录提供自己的 `.eslintrc`
"css_modules": false,
"transfer_assets": false,
"base64_image_limit": 10240,
"esmode": 'es6' // swith esmode on template creating, es5/es6, default to es6
}
默认HTML模版
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="keywords" content="webpack, react, es6, build tools"/>
<meta name="description" content="webpack auto build tools intergated with one command"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="format-detection" content="telephone=no"/>
{% if (o.htmlWebpackPlugin.files.favicon) { %}
<link rel="shortcut icon" href="{%=o.htmlWebpackPlugin.files.favicon%}">
{% } %}
{% for (var css in o.htmlWebpackPlugin.files.css) { %}
<link href="{%=o.htmlWebpackPlugin.files.css[css] %}" rel="stylesheet">
{% } %}
{% if(o.chunkManifest) { %}
<script>{%#o.chunkManifest%};</script>
{% } %}
<title>frontend-build-tools</title>
</head>
<body>
<div id="app">
</div>
{% for (var chunk in o.htmlWebpackPlugin.files.chunks) { %}
<script type="text/javascript" src="{%=o.htmlWebpackPlugin.files.chunks[chunk].entry%}"></script>
{% } %}
</body>
</html>
- 注: 首页模板支持pepper.configs.js配置的api, static, mode, globals等全局变量。具体用法:
<link rel="shortcut icon" href="{%=o.configs.STATIC%}assets/bundle.css">
<script>
if ("{%=o.configs.MODE%}" == 'release') {
he('send', 'error', {err: s.substr(0, 999)});
}
</script>
API
cli 命令 | 说明 |
---|---|
pepper init name | es6 & react-router |
pepper init-redux name | es6 & react-router & redux |
pepper init-rn name | react-native (演出票 DEMO) |
pepper page name | 创建页面 |
pepper component name | 创建组件 |
pepper upgrade | 版本升级 (gitlab pull) |
pepper start -p PORT | 本地调试,基于 start 配置 |
pepper test | 运行测试代码, 基于 test 配置打包, 可后缀 -s 启动服务 |
pepper pre | 基于 pre 配置打包,压缩, 可后缀 -s 启动服务 |
pepper release | 基于 release 配置打包,压缩,移除 console 日志, 可后缀 -s 启动服务 |
pepper library mode | 基于 mode test, pre, release 模式将项目按照 umd 格式打包成类库,类库名称 package.json name 属性制定, 使用参考 |
也可以这样玩耍 (项目目录下输入 pepper)
➜ pepper
? 选择要执行的任务:
项目打包
代码格式校验
开发调试
❯ 初始化新项目 (es5)
初始化新项目 (es6 & react & react-router)
初始化新项目 (es6 & react & react-router & redux)
初始化新项目 (react-native & redux)
(Move up and down to reveal more choices)
常见问题
clone 后的 pepper 要放到哪里?
一定不要放到项目目录下,一定不要放到项目目录下,一定不要放到项目目录下,(建议放到应用程序目录,pepper 也是个程序嘛)
程序入口在哪里?
在配置项中的
pages
有说明,它就是整个程序的入口,默认使用pages/index
文件。这里定义了程序的路由配置,path='/' component={INITIAL_PAGE}
,INITIAL_PAGE
就是应用的首页import PAGE from 'react-proxy?name=PAGE_NAME!./page_path
是什么意思 ?这个是使用 react-proxy-loader 对页面进行拆分,由于每一页面对应一个Router,从而实现了页面的按需加载。当然,如果不需要页面的懒加载功能,可以直接这样引用
import PAGE from './page_path'
怎么在组件或者页面中引用图片?
首先,图片、字体等静态资源要统一放到
assets
目录中去。 其次,确保pepper.cofig.js
中的alias
中有assets
的配置之后,对于 js 中的图片地址,要先 import IMAGE from
assets/paths/to/your/image
, 然后<img src={IMAGE} />
就可以了SCSS 中的图片引用,要这样处理
background-image: url(~assets/paths/to/your/image)
字体文件引用报错
对于本地字体文件的引用,请去除文件后缀名之后的所有参数(hash 或者 queryStr 之类的)
多个 html 文件
不同的页面入口文件,可指定不同的 html 模版
chunkManifest的异步加载模块crossOrigin属性问题
release打包后,项目需要异步加载模块时,如果pepper.configis.js的globals存在crossOrigin变量,则把crossorigin属性加到script中
效果如:
<script type="text/javascript" crossorigin="anonymous" charset="utf-8" async src="//mqqstatic.wepiao.com/tld/js/cinemas-e9243a4.js"></script>
具体配置:
globals:{ "crossOrigin": { "start" : "anonymous", "test" : "use-credentials", "pre" : "use-credentials", "release" : "anonymous" } }
.
├── [ 232] README.md
├── [ 170] dist
├── [ 547] mock.js
├── [1.8K] node_modules
├── [ 391] package.json
├── [2.8K] pepper.config.js
├── [ 238] src
├── [1.1K] template.html
└── [ 687] test.html
pepper.config.js
配置多页面入口
// custom default page dir
"pages": {
// 生成的 html 文件的名称
index: {
// 入口文件路径,相对于 src 目录下
entry: 'pages/index',
// 模版文件路径 相对于 根目录
template: 'template.html'
},
test: {
entry: 'pages/test',
template: 'test.html'
}
},
最后打包生成不同的 html 文件 ( pepper release )
Hash: c55a6f52505a36434410
Version: webpack 1.13.2
Time: 7106ms
Asset Size Chunks Chunk Names
js/index-47dbd820.js 57.6 kB 0, 4 [emitted] index
js/home-819f5bf8.js 10.2 kB 1, 4 [emitted] home
js/test-d4588b46.js 500 bytes 2, 4 [emitted] test
js/vendor-d10e59ab.js 131 kB 3, 4 [emitted] vendor
js/manifest-e2ed8267.js 1.29 kB 4 [emitted] manifest
index.html 1.95 kB [emitted]
test.html 1.59 kB [emitted]
[0] multi vendor 40 bytes {3} [built]
+ 239 hidden modules
pepper 怎么升级
墙裂建议采用 gitlab 本地安装,这种方式升级较容易(终端中执行:
pepper upgrade
,任意目录皆可)Start 模式下 替换 html 模版文件中的字符串
场景:html 文件中包含特定格式的字符串占位符,上线时该字符串由线上发布机替换成真实的值 问题:线下开发,无法处理字符串占位符替换问题,阻碍开发进程 解决方案:指定一个特定的文件,包含要替换的逻辑以及对应的值,每个 html 模版对应一个该文件,运行时做替换处理
pepper 配置如下:
单模版 html 配置:
"template": { "path": "src/template.html", // custom template path, omit it if your desire to use inner template "mock": "src/template.mock.js", // the replacement rules "favicon": "assets/images/favicon.ico" },
多模版 html 配置:
// custom default page dir "pages": { "index": { entry: "pages/index", template: "src/template.html", // target html to be replaced mock: "src/template.mock.js", // the replacement rules }, "share": { entry: "pages/share", template: "src/template.html", mock: "src/template.mock.js", } },
替换文件的规则:
// 多个数组 modules.exports = [ // 子数组,前者替换规则的正则表达式, 后者为要替换的值 [ /\[\[\[sSharePic\]\]\]/g, "http://wx.wepiao.com/favicon.ico" ], [ /\[\[\[sShareTitle\]\]\]/g, "微信电影票" ], [ /\[\[\[sShareContent\]\]\]/g, "娱票儿,微信电影、演出票" ], [ /\[\[\[appShareChannels\]\]\]/g, "1,3,4" ], ] // 没有使用键指对的原因在于,key 不能为正则表达式
注意:该规则只在开发(start)模式下有效,测试,预上线和线上由发布机做处理
关于用 pepper 打包公共组件库的说明
现在 pepper 支持将项目按照 umd 的格式,打包成公共类库,跨项目使用。这个是为了解决一些公共组件跨项目使用的问题。
- 按照 npm 的规范,将项目配置成也发布的格式。
- 在 pepper.config.js 中制定库的入口文件, 默认
src/index.js
├── demo
├── package.json
├── pepper.config.js
├── src
│ ├── Banner
│ ├── FullScreen
│ ├── Picture
│ ├── index.js
│ ├── style.scss
│ └── utils
└── yarn.lock
具体参见 Advertisement 项目配置
关于 npm 的常见问题
npm install
这个命令会拉取
package.json
的dependencies
,devDependencies
列表中罗列的依赖包,并存放到node_modules
中去。一般会在初次clone
项目时用到。还有就是,如果某次代码更新后,packages.json
中有变动,或者终端中提示未找到某个模块之类的错误,也要执行下npm install
npm install PACKAGE --save
指在项目中安装PACKAGE
依赖包,并保存到package.json
的dependencies
中去。npm install PACKAGE --save-dev
指在项目中安装PACKAGE
依赖包,并保存到package.json
的devDependencies
中去。--save
和--save-dev
的区别在于,前者是代码逻辑中的依赖(React),后者只是起辅助(代码校验,编译等等, 线上代码并不包含) 具体参考这里npm shrinkwrap
这个会锁定依赖包的版本,而不是在每次
npm install
时使用最新的patch version
举个例子,项目中依赖vision-ui@^1.2.11
,如果有新版vision-ui@1.2.12
,那在首次npm install
的时候就会下载vision-ui@1.2.12
而非vision-ui@1.2.11
。这个与 npm 升级策略有关。强烈建议开启此项。 具体参考这里
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago