fes(front end scaffold),发音:/fes/。它是基于 webpack4、koa2 搭建的多页面开发环境。高效开发,快速打包。
create-fes 是一个构建 fes 多页面应用的命令,灵感来源于 create-react-app。
🌴为什么我要构建这个脚手架 🌴
singsong:架构图中的 sass-loader、twig-loader 只是用于说明,不代表 fes 模板语言只支持 twig、css预处理器只支持 sass。可以是其他模板言语、或其他 css 预处理器。
fes 以 HTML 的文件名来关联 JS 和 DATA。 其中 JS 和 DATA 是可选的。而 SCSS 则通过 JS 引入,再使用 mini-css-extract-plugin
来优化。另外,fes 还提供了 build
、start
、preview
、tmpl
脚本命令。
- 多页面开发环境。
- js-code-splitting、css-code-splitting。
- proxy
- css autoprefixer
- css/svg sprite
- 支持灵活定制,如自动打开浏览器、热加载、生成二维码等配置。
- 自动监听 port,如果被占用,提示性切换。
- 打包优化分析。
- 模板输出(便于后端复用模板)。
- 基于mockjs 模拟 api。
- 支持模板语言 loader 的配置。
- 自动优先使用 yarn 安装依赖包。
- 支持 css 预处理器 loader 的配置。
- 针对 dev,提供了 focus 功能。
- 针对 build,提供了 foolMode、debug 功能。
- 支持路由配置。
- 支持多级目录结构。
- 支持 preview、tmpl 预览。
- 支持 CSS-Modules。
- 支持 typeScript。
- 支持 service worker。
npm install create-fes -g
如果不想安装create-fes
,可以直接使用npx
命令(推荐)
npx create-fes <project-name>
- 默认
create-fes example
-B, --no-babel
表示是否关闭babel
。默认开启babel
。
create-fes example -B
// or
create-fes example --no-babel
-t, --typescript
表示是否开启typeScript
。默认关闭typeScript
。
create-fes example -t
// or
create-fes example --typescript
-n, --npm
表示直接使用npm
安装依赖包。
create-fes example -n
// or
create-fes example --npm
--scripts-version <alternative-package>
表示使用一个自定义fes-scripts
版本。
create-fes example --scripts-version 1.0.x
-h, --help
表示获取帮助信息。
create-fes example -h
// or
create-fes example --help
在使用 create-fes
命令创建 fes-app 过程中,会提供模板选择功能:
What template do you need?
pc
other custom template(<path-to-template>)
选择 other custom template(<path-to-template>)
选项,提示
Please input a valid path of template?
$ /path/to/your/template #输入模板绝对路径
├── .babelrc ---> babel配置文件
├── .browserslistrc ---> browserslist 配置文件。postcss、babel 会根据其配置进行编译。更多参考: https://github.com/browserslist/browserslist
├── tsconfig.js ---> typeScript配置文件
├── README.MD
├── package.json
├── app.config.js ---> app 配置文件
├── build ---> 打包文件夹
├── config ---> 配置文件夹
├── public ---> 公用资源
└── src ---> 源代码文件夹
如果 app.config.js
提供的配置项不能满足你的项目需要,可以通过 webpack.dev.config.js
和 webpack.prod.config.js
进行重写定制。
├── webpack.dev.config.js
└── webpack.prod.config.js
├── api ---> 使用 mockjs 模拟 api
├── assets ---> 资源文件
├── javascripts ---> js 源代码文件夹(根据该目录下直接 js 文件生成 entry)
├── mock ---> 模板变量数据。支持 js、json 格式,及多文件数据(index.1.json, index.2.json.....)。其中 `common` 是公用 mock 数据。
├── styles ---> scss 源代码文件夹
└── views ---> template 源代码文件夹
-
isHot:是否开启热加载,默认为
true
。只在开发模式下有效。 -
proxy:配置 proxy。详细配置参考……
-
babelLoader:配置babel-loader,默认为
{}
。详细配置参考…… -
spritesConfig:配置 sprites。详细配置参考……
-
urlLoader:配置url-loader。详细配置参考……
-
sw:service worker 配置,默认为
{}
。详细配置参考…… -
tsChecker:fork-ts-checker-webpack-plugin 配置,默认为
{}
。详细配置参考…… -
extraDependencies:增加额外的依赖文件。方便开发修改时,能自动编译。相对于 'src' 目录,支持
'**/*.js'
形式。详细配置参考…… -
tmplLoader: 设置模板语言 loader, 默认为
twig-loader
。tmplLoader: { test: /\.pug$/, loader: 'pug-loader', options: {}, }
-
styleLoader: 设置css预处理 loader,默认为
sass-loader
。如果不想使用任何预处理器,只需将styleLoader: false
即可。styleLoader: { test: /\.less$/, loader: 'less-loader', options: {}, }
-
htmlLoaderOptions:
html-loader
的 options。 -
alias:alias 配置项。其中
@
表示 'src' 目录。 -
provide:provide plugin 配置,默认为
{}
。详细配置参考…… -
mockConfig:配置模板数据以接口的形式提供。
mockConfig: { // 访问路径作为key '/index': { // 提供渲染mock数据接口 api: 'https://postman-echo.com/get?page=index', // 格式化接口数据 format: data => data.args, }, '/fes/info': { api: 'https://postman-echo.com/get?page=info', format: data => data.args, }, },
-
routerConfig:路由配置项,可以自定义页面的路由映射。
'/your/path': 'index.html' // 默认:'/index': 'index.html'
-
cssModules:配置 css modules,默认为
'global'
。详细配置参考……。如果不需要,建议关闭。这样可让 webpack 编译更快。 -
dev:开发模式
- port:端口号,默认为
3000
- autoOpen:是否自动打开浏览器,默认为
true
。支持 boolean 、String。如果存在/index
, 默认打开/index
,否则其中某个页面。如果是字符串(如: '/home'),就当成打开路径。如果路径不存在会回退到 boolean。 - qrcode:是否生成预览二维码,默认为
true
- sourceMap:是否开启 sourceMap,默认为
true
。 - devtool:配置 devtool,默认为
'cheap-module-source-map'
。详细配置参考…… - focus:表示只编译指定的路由模板文件,提高编译速度。支持 String、Array,默认值为
''
。
- port:端口号,默认为
-
build:生产模式
- foolMode:开启 fool 模式,如果开启会关闭 splitChunks。默认为
false
。 - debug:开启 debug 模式,不会对打包文件进行压缩处理。
- publicPath:输出路径,默认为'/'
- outputPath:配置资料文件输出路径。支持字符串或对象,字符串表示path。如果想精细定制,可以使用对象形式:
{path, filename, chunk(仅js有效)}
- isHash:是否开启 hash。默认为
true
- css:css 输出路径
- others:除了 css、img、js 文件外的资源输出路径
- img:img 输出路径
- js:js 输出路径
{ path: 'static/css/', filename: '[name].[chunkhash:8].js', chunck: '[name].[chunkhash:8].chunk.js', }
- isHash:是否开启 hash。默认为
- report:是否生成打包分析报告,默认为
false
。支持 boolean 、object。如果为true
,使用默认配置生成分析报告。如果为配置 object, 会根据该配置对象生成分析报告。配置object - isTmpl:是否输出后端模板,默认为
false
- sourceMap:是否开启 sourceMap,默认为
false
。 - devtool:配置 devtool,默认为
false
。详细配置参考…… - htmlMinify:是否压缩html文件,默认
false
。详细配置参考…… - optimizeCssAssetsPlugin:压缩 css 配置。详细配置参考……
- splitChunks:splitChunks 配置。详细配置参考……
- foolMode:开启 fool 模式,如果开启会关闭 splitChunks。默认为
-
tmpl:tmpl预览模式,注意:该模式只能在
isTmpl: true
生效- port:端口号,默认为
3100
- autoOpen:是否自动打开浏览器,默认为
true
- qrcode:是否生成预览二维码,默认为
true
- port:端口号,默认为
-
preview:预览模式
- port:端口号,默认为
3030
- autoOpen:是否自动打开浏览器,默认为
true
- qrcode:是否生成预览二维码,默认为
true
- port:端口号,默认为
- 开发
npm start
- 打包
npm run build
- 预览
npm run preview
- 预览后端输出模板
npm run tmpl
-
Background
在前后端复用模板时,存在一个问题(不知道大家是否有这样感觉):在拼接模板时,模板变量数据需要后端以文档形式给出。但这样不仅存在信息同步性的问题,而且前后端开发起来不是很方便。前端需要对模板数据进行 mock,有时很难模拟线上数据环境;后端更新数据结构时,可能没有及时同步给前端等
-
Solution
这里需要后端对模板渲染数据做些额外的处理工作。需要额外提供一个包含了渲染模板的数据的接口供前端使用(只存在开发环境下,在上线时需要关闭掉)。这没有什么开发成本。只需对该接口定义特定前缀,然后在模板渲染逻辑之前拦截输出数据。这样不仅能保持数据一致性,而且维护起来也方便。
-
Usage
mockConfig: { // 访问路径作为key '/index': { // 提供渲染mock数据接口 api: 'https://postman-echo.com/get?page=index', // 格式化接口数据 format: data => data.args, }, '/fes/info': { api: 'https://postman-echo.com/get?page=info', format: data => data.args, }, }
同时开发模式下可以输入
mock
指令来获取对应的 mock 数据$ mock Mock Data: { "common": "commons", "name": "fes-index-page", "data": { "name": "fes" } }
另外,除了
mock
指令,还提供了如下指令:- mock: 查看当前的 mock 数据
- view: 打印范围地址和二维码信息
- clear: 清空控制台
注意:默认开启 global
模式,要使用需要主动声明 local
- scss
/* 文件名为:_cssm.scss */
:local(.cnt){
position: fixed;
left: 0;
top: 30%;
background-color: rgba(54, 54, 54, 0.486);
box-shadow: 1px 1px 0.2rem rgba(2, 2, 2, 0.568);
:local(.tt){
font-size: 1rem;
color: rgb(133, 233, 150);
}
:local(.des){
background-color: rgb(19, 19, 19);
color: #fff;
}
}
- html
<div class="cssm"></div>
- JS
import cssm from '../styles/modules/_cssm.scss';
const getCssmHtml = cssmObj => (`
<div class="${cssmObj.cnt}">
<h3 class="${cssmObj.tt}">css-module</h3>
<p class="${cssmObj.des}">介绍fes中css-modules的使用</p>
</div>
`);
const cssmContainer = document.querySelector('.cssm');
cssmContainer.innerHTML = getCssmHtml(cssm);
注意:图片的引用必须相对于入口页面,推荐使用绝对路径引用方式。因为如果存在多级入口的目录结构很难维护相对引用方式
html:绝对路径引用
<!-- alias: @:/Users/singsong/github/fes/src -->
<img src="@/assets/puppy.jpg" alt="">
<div style="background-image: url('${require(`@/assets/puppy.jpg`)}')">
html:相对路径是相对入口 html 文件引用
<!-- 直接引用 -->
<img src="../assets/puppy.jpg" alt="">
<!-- 嵌入方式 -->
<div style="background-image: url('${require(`../assets/puppy.jpg`)}')">
scss:相对路径是相对入口的 scss 文件引用
.icons {
background-image: url(../assets/husky.jpg);
position: relative;
padding: 10px 40px;
overflow: hidden;
background-color: #cbce08;
.ant {
float: left;
background: url(../assets/sprite/ant1.png) no-repeat 0 0;
height: 64px;
width: 64px;
&:hover {
background-image: url(../assets/sprite/ant2.png);
transform: scale(1.2);
}
}
}
scss:绝对路径引用
// alias: @:/Users/singsong/github/fes/src
.icons {
background-image: url(~@/assets/husky.jpg);
position: relative;
padding: 10px 40px;
overflow: hidden;
background-color: #cbce08;
.ant {
float: left;
background: url(~@/assets/sprite/ant1.png) no-repeat 0 0;
height: 64px;
width: 64px;
&:hover {
background-image: url(~@/assets/sprite/ant2.png);
transform: scale(1.2);
}
}
}
可以开启css modules
,不过它更适合与 js 混合开发模式,如css-in-js、react、vue 开发。
- CSS modules break build if used with
~
- @imports not resolving when css-modules enabled
- CSS Modules & Sass in Create React App
- 支持其他常用的模板引擎,同时增加对应的模板。
- 完善文档,增加 examples