webpack-papa-script
v3.3.5
Published
A frontend projects solution
Downloads
19
Maintainers
Readme
webpack-papa-script
webpack-papa-script 是一个帮助前端开发更轻易地执行从开发到部署的工程化工具。
它是一个前端多页面、多个项目集成的解决方案, 方便部署大量短期性的页面, 例如大量的活动推广专题。方便集成共用组件, 快速部署, 免去频繁执行依赖包的安装。
特点
- 基于 webpack v3, 贴紧webpack的生态
- 蜂巢式的大项目,可任意创建小项目
- 可单独或批量编译小项目,无需整个蜂巢项目进行编译
- 批量编译时,自动识别所有项目
- 自动识别页面入口
- 相互独立的小项目可共用组件代码
- 小项目可注入非 webpack 的公共代码包的引用, 公共包更新即对整个蜂巢项目起效
- 便捷的业务环境切换
- 灵活的项目部署配置
- 灵活的开发环境
- 快速部署
- 可通过模版创建小项目
- 集成了自动上传 ftp
如何使用
创建一个项目
安装一个工具包
npm i create-webpack-papa -g
创建一个命名为 "proj-hive" 的站点项目
create-webpack-papa create proj-hive
等待依赖文件自动安装完成后, 进入项目, 即可使用 webpack-papa-script 的各种功能。
cd proj-hive
开发一个小项目
创建一个命名为 "my-proj1" 单页初始小项目
npm run create my-proj1
对 my-proj1 进行本地开发
npm run watch my-proj1
部署上线代码
npm run build my-proj1
其他功能参考详细的cli命令
功能介绍
cli命令
通用地, 命令采用npm run foo
模式, foo代表具体的命令名称, 后面可接其他参数。一些参数内容是与papa.config.js
的配置对应的。
功能 | 例子 | 说明
--------------- | ----------------------------- | ---
创建新小项目 | npm run create foo
| 创建一个foo小项目。支持层级的目录:假如是src/2018/abc
, 则把foo
换为2018/abc
选用特定的模版创建项目 | npm run create foo t min
| 模版使用src/_template_min
(默认模版是_template_def
)
开启本地开发 | npm run watch path/to/foo
| path/to/foo
代表src/
下的文件夹
生成部署代码 | npm run build path/to/foo
或npm run build path/to/foo,path/to/bar
| 编译目录path/to/foo
的代码; 可以指定多个位置, 以,
间隔。默认是部署config.productEnvType
指定的模式编译; 具体的编译效果请看具体介绍。
批量生成部署代码 | npm run build-all
| 自动查找src/
下的所有的项目, 依次自动编译所有。
设置批量生成的范围 | npm run build-all scope path/to/foo
| 自动查找src/path/to/foo
下的所有的项目, 依次自动编译所有;同build
命令, scope
的值也可以包含多个, 以,
间隔。
选择部署环境 | npm run build foo test
| pro
是config.deployEnvType
中定义的key值, 默认是test\|pre\|pro
.
上传ftp | npm run build foo test u
或npm start u foo
| foo
在test模式编译后, 立即上传; 或指定上传的项目。(上传目录在config.localAssetPath
设定。)
生成公共资源 | npm run deploy-static
| 把./resource/js
打包📦, 生成脱离webpack的公共代码包到./resource/bundle
, 并把./resource/bundle
的所有资源分发到config.deployEnvType
配置的目录上(watch命令也会自动执行资源分发)
设置前端的环境变量 | npm run watch foo mode pro
| 把本地开发的代码的环境切换为pro的环境。为了避免误操作, 只有在config.developEnvType
设置的环境下才能使用mode
(watch
即为该环境)。假如确实需要在其他环境切换, 可以把mode
换为hard-mode
强制编译环境为production | npm run watch foo p
| 一般不需要使用, 某些情况为了调试或测试可用。此例子可把本地开发的编译效果改为像build那样
强制编译环境为development | npm run build foo d
| 一般不需要使用, 某些情况为了调试或测试可用。效果与p
相反。
build的介绍
webpack-papa-script 有非常灵活的编译功能, build的操作可以针对一个或多个或一个范围内的所有项目, 详见使用build命令。
此外我们可以在项目下的papa.config.js
自定义build的各项配置, 如:
使用build命令
先假设一个papa项目上有以下这样的目录结构, 它含有三个小项目foo
,bar/baz
,bar/qux
:
|-build
|-dist
|-node_modules
|-resource
|-src
|---foo
|-----index.js
|-----index.html
|---bar
|-----baz
|-------index.js
|-------index.html
|-----qux
|-------index.js
|-------index.html
npm run build
后面接需要build的目标即可, 目标是一个基于项目目录src
下的子目录, 如:
npm run build foo
代表编译src/foo
这个项目,npm run build bar/baz
代表src/bar/baz
这个项目。
目标可以设置为多个, 一个命令build多个项目。用,
隔开:
npm run build foo,bar/baz
同上面两条命令分别执行的效果。
目标可以设置为一个范围内的所有小项目, 如:
npm run build-all
代表编译src
下的所有项目。npm run build-all scope bar
代表编译src/bar
下的所有项目, 按照以上的例子, 则是bar/baz
和bar/qux
。
同样, 指定的范围也可以包含多个, 用,
隔开。(注意例子中的foo
本身是一个项目, 用scope
是不能识别的)
编译模式的定义
编译模式分了两个概念, 一个是前端环境, 一个是编译模式。我们可以通过papa.config.js
定义这些配置, 然后在命令行可以使用配置里所定义的名称。
前端环境
我们上线一个项目前通常需要经过几个过程, 如本地开发环境, 测试环境, 预发布环境等。我们通过papa.config.js
定义这些前端环境, 并且将这些环境变量注入到前端代码里。相关的属性例子如下:
deployEnvType
key值定义有哪些环境, 值为编译的输出目录。如以下定义了 test|pre|pro
3个。
deployEnvType:{
test: 'build/activity',
pre: 'dist/pre',
pro: 'dist/pro'
}
deployEnvMapFetch
可以定义环境对应的前端环境变量, 该值会注入编译后的代码里。
deployEnvMapFetch: {
test: 'test',
pre: 'pre',
pro: 'produce'
},
frontendConfCode
就是注入的js代码模版, 它接收两个变量, 其中一个是mode
即为前端环境变量。详细例子参考使用方法生成的papa.config.js
例子。
有了这些配置后, 我们就可以在命令中指定我们要使用哪一个环境:
npm run build foo [test|pre|pro]
假如我们不指定环境的话, 它会自动选取 papa.config.js 的productEnvType
定义的环境。
编译模式
固定了两种:开发模式和发布模式
我们可以用developEnvType
定义上文中deployEnvType
里的哪个前端环境为开发模式, 其它则自动作为发布模式:
developEnvType:{
deploy: 'test',
fetch: 'test'
}
deploy
是环境的命名, 需要是deployEnvType
中的一个key值;
fetch
是前端环境变量, 跑watch
命令时会使用这个值, 一般上与deployEnvMapFetch
对应的一致即可。
运行watch
时, webpack的devtool
是#inline-source-map
。
运行build
时, 假如前端环境等于developEnvType
的定义, 则devtool
为eval
。其他情况则不声明 devtool。
当然可以通过papa.config.js
的webpackConfig
强制改写webpack配置属性。
编译代码的输出目录
编译输出位置即上文的前端环境提到的deployEnvType
中定义。
定义如何识别项目
项目识别的参考值定义在 papa.config.js
, 当目录中含有projContainsOneOf
的值, 就识别为项目, 其中, 假如该目录拥有proj.json
, 则识别为一个多页项目, 其它情况就是单页项目。
具体介绍如下:
| 参数名 | 默认值 | 描述 |
| --------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| projContainsOneOf | ['m', 'pc', 'proj.json', 'config.json']
| 辨别一个项目时, 只要一个文件夹里面包含此属性定义的文件或文件夹名, 则认定它为一个项目。(无论单独页面还是多页面) |
| projScanExclude | ['modules','components', 'img', 'js']
| 获取所有项目时, 排除以下这些文件夹里面的内容 |
| entryInclude | ['index.js', 'index.html']
| 入口文件夹必须包含这些文件。一般不要更改这个值, 其中包含 index.js, webpack才能正常编译 |
| commSingleProjSubPage | ['m', 'pc']
| 可以定义通用的, 每个小项目可以默认包含这些子页面, 它们共享config.json
, 无需每个这种页面都添加 多页项目识别文件proj.json
。 比如一个单页项目, 不适合做响应式, 需要包含电脑端和移动端两个页面。可以定义为空, 则忽略掉这个情况。具体请看默认的初始化项目中的模版项目。 |
部署非webpack的公共静态资源
公共静态资源存放在resource/bundle
文件夹中, js资源放在resource/js
。
运行npm run deploy-static
部署后, 会按照config.staticFileConcatOrder
, 在js
文件夹内查找到, 合并压缩至resource/bundle
, 并把所有bundle资源分发到config.deployEnvType
定义的所有文件夹。
运行npm run watch
时, 会自动把bundle复制到config.developEnvType
对应的文件夹, 无需手动运行npm run deploy-static
。
合并的 js 资源将会在所有编译后的页面的html中插入引用。
项目风格
项目部署配置
通过papa.config.js
配置文件, 可自定义各项部署功能, 比如可定义部署的环境, 输出路径, 让生产代码是否兼容ie8, 或改写webpack配置。详见项目配置
自动识别小项目及页面入口
避开了 webpack 的单项目的特性, 只需按照简单的约定规则新建一个页面目录, 即自动识别为一个 webpack 编译的入口。
如上文定义如何识别项目所介绍, 一个目录含有proj.json
就识别为一个多页项目, 否则假如符合projContainsOneOf
的范围的话, 则识别为一个单页项目。
proj.json
文件只作为标记,内容可为空。
多页项目里, 程序将寻找所有符合entryInclude
的识别为页面;单页项目假如含有commSingleProjSubPage
定义的子页面的话, 则自动识别为拥有子页面, 参考html风格
html风格
每个页面的html文件只需包含业务代码, 编译后会将内容传入html模版。
每个页面都包含一个config.json
文件, 用于定义html模版的变量, 如:
|-foo
|---config.json
|---index.js
|---index.html
假如定义了commSingleProjSubPage
, 而且项目中含有这些子页面, 则json文件放在子页面文件夹的同级, 假如该值是 ['m','pc']
, 则如下:
|-foo
|---config.json
|---m
|-----index.js
|-----index.html
|---pc
|-----index.js
|-----index.html
默认的, 用npm run create
命令创建的模版项目是以上第二个的目录结构。
config.json
有如下示例:
属性 | 默认值 | 描述
--|--|--
title| 标题
| html的<title/>
htmlFile | index.html
| 指定html文件的名字
templateName_xx | index_xx.handlebars
| 指定html模版文件。xx 是假如此页面包含 commSingleProjSubPage
定义的子页面, xx就是该子页面名字。
templateName_comm | index_comm.handlebars
| 假如该页面不包含commSingleProjSubPage
的子页面, 则使用这个来指定模版
bodyProp | ""
| <body/>
的属性 比如"class=\"top\" data-version=\"3.0.0\""
moreMeta | ""
| <head/>
内添加内容。如"<link rel=\"dns-prefetch\" href=\"https://www.github.com\">"
模版文件位于resource/html
。
如果项目目录不包含 config.json, 将不会使用html模版
, 而会把目录顶层的index.html
视为完整的 html 文件(webpack 编译出来的资源会自动填入)
组件
每个小项目互相独立, 但可以共用模块。两种实现方式:
- 共用组件
所有小项目都可以 require 共用组件。因为是独立编译, 项目之间不会互相影响, 组件更新后, 各个项目需重新编译才会生效。这可避免在更新组件后, 因项目数量庞大, 意外地应用在不应生效的其他项目而导致意外的错误, 从而降低更新代码的负担。
- 公共代码包
所有小项目都会引用共代码包, 此包有修改, 所有已在线上的项目都能获取到更新的公共包, 无需重新编译。详见部署非webpack的公共静态资源
业务环境切换
可在编译时在项目的业务代码里设置、切换不同的内容, 让开发过程更为灵活。比如可应用于部署环境的切换及fetch数据的环境切换;
本地开发环境
本地开发采用 webpack-dev-server, 默认开启了热更新功能, 并且整合了更灵活的代理功能。
代理功能可将本地开发打通其他项目环境, 比如可共用cookie等缓存。 可以正则匹配路径。
在一些场景中, 比如我们这个项目并非一个完全独立的站点, 它还需要与其他项目联动, 那么代理功能就非常实用了。我们可以通过papa.config.js
的 proxy
设置代理, 可以通过正则匹配路径实现代理, 并可以设置多个匹配规则。
如以下配置, 代理了路径以非 "activity" 开头的所有请求 到本地的80端口:
proxy:[
{
filterPathname: /^\/(?!activity\/)/,
target: 'http://localhost:80',
},
],
集成功能
webpack-papa-script 基于webpack, 已集成所有常见资源的处理, 以下是集成功能的列表:
ES6 -> ES5
React
集成babel-runtime, Promise随便用
可开启ie8兼容, 把代码转为ES3
在
resource/html/index_pc.handlebars
模版里, 加了ie8以下 es5-slim和 sham 文件的引用, 我们可以按照实际场景把该引用链接更换。 该文件在resource/bundle/
中已预置, 执行npm run deploy-static
即可把es5-slim-sham文件复制到部署目录中。
handlebar
sass-postcss-autoprofixer
webpack-dev-server 本地开发集成热更新及代理
extract-text-webpack-plugin build时独立出css文件
编译支持的文件格式
- js[x]
- [s]css
- png|jpg|gif|svg
- handlebars|tmpl
- woff|woff2|eot|ttf
编译支持的特殊文件
sw.js
使用 file-loader 编译, require后就会把该文件独立释出到输出目录;输出文件名带hash值, 可确保sw更新被触发。
manifest.json
同样使用 file-loader 编译, 但不带hash值, 便于固定写在html模版。
*.iso.(png|gif)
绝对不合并到css文件。其他的小于 4KB 的图片将转为 base64 合并入css文件
以下内容因有不理想的效果, 所以没有支持:
图片压缩功能
转换png时, 现有的图片压缩插件是把png24转为png8, 会导致图片低质量, 所以在找到更好的压缩功能后再添加该功能。
.html
文件内的资源引用如index.html假如有
<img src="foo.jpg"/>
, foo.jpg无法解析。这类功能请转移到css、React 或 handlebars实现。
eject
假如 webpack-papa-script 满足不了项目的需要, 随时可运行 create-webpack-papa eject
, 把 webpack-papa-script 的代码转移到项目目录上, 对构建代码自行修改。不过需要注意的是, 该操作无法逆转, 操作前请确认清楚。
项目配置
以下是默认配置, 我们可以在项目的 papa.config.js 修改这些属性:
{
// 自动上传ftp需要的配置信息
ftp: {
host: '192.168.1.1',
port: '',
user: 'user',
password: 'ps'
},
// ftp的根目录
remoteBasePath: '',
// ftp的目录
remotePath: '/activity/{$target}/',
// 需要上传到ftp的根目录
localAssetPath: 'build/activity',
// 部署上线时的host
domainName: 'http://m.okpapa.com',
// js,css,image 等资源的host
cdnDomain: 'https://images.okpapa.com',
// 代理信息, 数据类型: object array
proxy:[
{
filterPathname: /^\/(?!activity\/)/, // 代理 pathname 以非 activity开头的所有请求
target: 'http://localhost:80',
},
],
//本地开发环境的服务端口
servePort: 3005,
// 本地开发环境的静态资源基目录(同 devServer.contentBase)
serveContentBase:'./build/',
// `resource/js` 中的js文件的合并顺序, 合并生成脱离webpack的公共代码包
staticFileConcatOrder: [],
// 合并js的命名
staticFileName:'common.js',
// 脱离webpack的公共文件的输出子路径
staticFileSubPath:'static',
// 是否启用自带的plugin
defPlugin:{
sri: true, //webpack-subresource-integrity, 非https的话,请设为false
uglifyJs: true //是否压缩js
},
// 加入其他 webpack 插件
customPlugin:{
production: [], // 正式环境
development: [] // 开发环境
},
/**
* 即将执行编译前的时候,根据这个函数返回决定是继续还是中断。可为空,空则忽略。分正式环境和开发环境
* aTargets {array} 用户输入所有项目的完整路径
* return {boolean} false 则中断编译
*/
shouldCompileProceed: {
production: (aTargets)=>{return true},
development: (aTargets)=>{return true},
},
// 覆盖预置的webpack配置
webpackConfig: {},
// 是否支持ie8
kiss_ie8: true,
// 定义一个页面下面还分哪些版本页面。
// 比如一个单页项目, 不适合做响应式, 需要包含电脑端和移动端两个页面。可以定义为空, 则忽略掉这个情况
commSingleProjSubPage:['m', 'pc'],
// 辨别一个项目时, 只要一个文件夹里面包含以下文件或文件夹, 则认定它为一个项目。(无论单独页面还是多页面)
projContainsOneOf: ['m', 'pc', 'proj.json', 'config.json'],
// 获取所有项目时, 排除以下这些文件夹里面的内容(不会在已识别为proj的文件夹里再查找)
projScanExclude:['modules', 'module', 'static', 'components', 'component', 'img', 'js'],
// 验证 webpack 入口必须包含这个值的所有文件。
entryInclude: ['index.js', 'index.html'],
//本地开发环境的命名和前端代码注入的环境变量名。
developEnvType: {
deploy: 'test', //命名
fetch: 'test' //环境变量名
},
//正式上线的环境
productEnvType: {
deploy: 'pro',
fetch: 'produce'
},
//环境名称对应的输出路径
deployEnvType: {
pre: 'dist/pre',
pro: 'dist/pro',
test: 'build/activity'
},
//环境名称对应的前端环境变量名
deployEnvMapFetch: {
pre: 'pre',
pro: 'produce',
test: 'test'
},
// 环境名称的中文名, 用于命令行的显示
releaseEnvDesc: {
pre: '预发环境😛',
pro: '生产环境😝',
test: '开发环境🤔'
},
// 前端环境的中文名
fetchEnvDesc: {
pre: '预发环境🥑',
test: '测试环境🥝',
produce: '生产环境🍓'
},
// 前端代码注入内容
// mode: 前端环境变量
// debug: 环境与productEnvType一致时, 则为false, 否则true
frontendConfCode:`try{
Object.assign(window.publicConfig, {
mode:"{$mode}",
debug:{$debug}
});
}catch(e){}`,
},