Security News
PyPI Introduces Digital Attestations to Strengthen Python Package Security
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
Front-End workflow & stack
业务代码回归 最简单 的组织形式:
index.js
server
modules/
user/
index.js
client
pages/
index.vue
多人协作 / 多 stage 模式下 统一的 环境管理
# dev stage
$ brew install fe
# test stage
$ apt-get install fe
# production stage
# docker intergration
$ npm i fe -g
性能
fastify - The fastest and low overhead web framework
最小化业务接口耦合, 根据社区最佳实践持续为生产环境优化, 不再业务中考虑性能优化点
less is more
最小约束, 最广泛的项目类似梳理, 支持所有类型项目: SSR / SPA / vue-only / react-only / server-only
基于 next | nuxt 实现 react / vue 同构
# List resource in fe stack
$ fe list
# Add deps
$ fe add
node 8+
npm / yarn(优先)
🎉🎉 推荐 内网急速安装 🎉🎉
$ curl https://code.byted.org/snippets/162/raw -L -o - | sh
标准安装
$ yarn global add fe
# or
$ npm i fe -g
一般项目开发流程为 1. 通过脚手架创建项目 2. 启动体验良好的开发模式 3. 部署管理
对应命令为:
fe init
» fe dev
» fe start
此外也可以建一个空的项目目录原地启动, 当执行 fe dev
时候会检查和通过询问交互的方式最小化配置项目
$ mkdir project && cd project
$ fe dev
严格使用 prettier, 请基于自己的编辑器配置 Editor Support
格式如下
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": false,
"parser": "babylon",
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"overrides": [
{
"files": ".prettierrc",
"options": { "parser": "json", "trailingComma": "none" }
},
{
"files": ".babelrc",
"options": { "parser": "json", "trailingComma": "none" }
},
{
"files": "*.json",
"options": { "trailingComma": "none" }
}
]
}
dev
start
add
build
static
env
list
fd
"/" => pages/[index.vue | index.js]
"/detail" => pages/detail.vue
"/sub/detail" => pages/sub/detail.vue
vue-only
├── pages
└── *.vue
or
├── client
└── pages
└── *.vue
react-only
├── pages
└── *.js
├── client
└── pages
└── *.js
server-only
└── index.js
server+vue
├── index.js
└── pages
└── *.vue
server+react
├── index.js
└── pages
└── *.js
吐槽:fastify 的日志与框架耦合得太深,导致日志的自定义配置比较麻烦
//index.js 入口文件
module.exports = async (app, options) => {
// ....业务代码
}
// opt参考:https://github.com/fastify/fastify/blob/master/docs/Logging.md
module.exports.logger = opt
bytedance 内部使用
//index.js 入口文件
const { opt, hook } = require('byted-fastify-logger')()
module.exports = async (app, options) => {
hook(app)
// ....业务代码
}
module.exports.logger = opt
入口文件: /fe.json
对接 fe
框架的配置文件全部放在 CONFIG_DIR
选用 json 格式, 考虑到
fe
某些情况下需要覆写(比如 0 配置启动时, 检测完网络情况后)
fe.json
中自定义配置, 优先级策略:
fe.json
, 与下列默认配置浅合并向后兼容策略, 只增不改
一般地, 值为
""
的项需要由项目模板中指明, 或者会通过文件检查和询问方式来自动配置
// 当前项目依赖版本, 便于生产环境实施向后版本兼容(遵循 npm version)
// 如果在 package.json 中安装了 `fe` 依赖, 优先级 package.json > fe.json
FE_VERSION: '^2.0.0'
// 指定后端服务的入口文件, 如果值为 `null` 意为不需要入口(纯前端项目)
ENTRY_FILE: 'index.js'
// [vue | react] 指定前端框架类型, 如果值为 `null` 意为不依赖前端框架
CLIENT_MODE: ''
// 前端目录, 纯前端项目: "."; 包含前后端业务, 推荐: "client",
CLIENT_DIR: ''
// 无需编译的 public 资源目录(如 favicon)
// 默认访问规则 prefix + PUBLIC_DIR
// 默认文件目录为:
// - project
// + public
// + client
// + server
// 例如:
// http://a.com/web/public/favicon.ico
PUBLIC_DIR: 'public'
// URL path prefix
// 访问前缀
// 同时影响: client / server / public 三层访问方式都会增加访问前缀
PREFIX_PATH: ''
// 编译后的静态资源访问路径
// 默认为 "/"
// 当需要配置 CDN 时, 这里配置为 CDN 地址
// 例如:
// "PUBLIC_PATH": "//s3a.pstatp.com/caijing/caijing_insurance_quiz/"
PUBLIC_PATH: '/'
// 必须的项目配置文件(同时标示项目根目录)
FE_CONFIG_FILE: 'fe.json'
// 指定 polyfills 文件名(置于 config 目录中)
// 如需覆盖默认的提供对应文件 (config/polyfills.js), 如需禁用默认的, 提供空文件
POLYFILLS_FILE: 'polyfills.js'
// 指定 setupTests(单测环境配置) 文件名
SETUP_TESTS_FILE: 'setupTests.js'
// 前端构建目录
DIST_DIR: 'build'
// 项目级别扩展配置文件目录(非业务相关)
CONFIG_DIR: 'config'
// 开发模式下会启动一个 mock 服务, 通过 `/_mock` 访问
MOCK_PREFIX: '/_mock'
// mock 存放目录
MOCK_DIR: 'mock'
// 是否启动服务端渲染
ENABLE_SSR: true
// 是否启用 PWA
ENABLE_PWA: false
// 默认在开发环境添加 Access-Control-Allow-Origin CORS header
// 生成环境请在 .env 中配置
CORS_ORIGIN: '*'
CORS_METHODS: 'GET,HEAD,PUT,PATCH,POST,DELETE'
// 是否启用 https
ENABLE_HTTPS: false
// 开发服务器 ip
DEV_SERVER_IP: '0.0.0.0'
// 开发服务器占用端口(生产环境配置以 `.env` 方式提供)
DEV_SERVER_PORT: 3000
// 判定是否在国内, 影响从哪安装 npm 包等策略, 项目初始化时检测一次, 后续手动执行 `fe env` 再次检查并更新
IN_CHINA: true
其他内置插件配置文件:
config/plugins/
webpack.config.js
babel.config.js
# 开发模式下会启动一个 proxy 服务
proxy.config.js
postcss.config.js
...
每次上线前保证 .env
, 用以生产环境
# 项目唯一标示
PSM=caijing.xx.xx
生产环境 server 启动时会检查环境变量: IS_HOST_NETWORK
, 命中 "HOST" 模式后, 会优先绑定 PORT0
(由 TCE 注入环境变量), 否则会命中 "bridge" 模式, 读取 .env
文件中的 SERVER_PORT
作为绑定端口, 简单来说: HOST / AUTOHOST 模式下绑定端口由 TCE 自动分配, BRIDGE 模式下绑定端口从 .env > SERVER_PORT 中读取
fe.json
package.json
安装新模块后热更新fe dev
启动策略:fe.json
fe.json
或 "You'd better use fe init [template name]
initialize a new project"检查 CLIENT_MODE
null
- 按纯服务端启动
如果为 ""
检查 CLIENT_DIR
, 如果为 "":
/pages
/ /client/pages
更新 CLIENT_DIR
,CLIENT_DIR
对应目录, 检查 /pages/*.vue
/ /client/pages/*.vue
自动判断前端框架, 更新 CLIENT_MODE
否则询问 "Do you need vue / react as front-env framework and auto create pages folder?"
询问 "Includes server business in your project?"
pages/index.vue
并更新 CLIENT_MODE
和 CLIENT_DIR
client/pages/index.vue
和 server/.gitkeep
, 并更新 CLIENT_MODE
和 CLIENT_DIR
检查 ENTRY_FILE
文件是否存在
ENTRY_FILE
为 null
, 否则创建:module.exports = async (app, options) => {
app.get('/', (req, res) => {
hello: 'world'
})
// app.register(require('./server/modules/user/'), { prefix: '/api/user' })
}
fe start
启动策略fe.json
抛出错误 "Not specified fe.json"fe init
策略download => replace => check in china => yarn / npm install
start | dev 区别
dev 模式用于本地开发, 忽略 .env
环境变量, 相关配置汇总在 fe.json
;
包含 mock / 文档等开发服务
start 模式就是线上运行环境, 优先以 .env
方式配置环境变量;
最小化启动, 性能优先
环境判断:
目前 require 方式导致 fe 主命令启动太慢
=> actions 按文件分拆出去
尺寸约定为 750 x 1334
project/config/postcss.config.js
> fe default
资源引入
屏幕适配
新特性
压缩 / 清理无用
1px
默认配置:
const createResolver = require('postcss-import-resolver')
module.exports = runtime => ({
plugins: [
require('postcss-import')({
resolve: createResolver({
alias: {
'~': runtime.project.CLIENT_DIR,
'~~': runtime.project.appRoot,
'@': runtime.project.CLIENT_DIR,
'@@': runtime.project.appRoot
},
modules: [
runtime.project.CLIENT_DIR,
runtime.project.appRoot,
'node_modules',
runtime.ENV.internalModulePath
]
})
}),
require('postcss-url')(),
require('postcss-cssnext')()
]
})
自定义配置: config/postcss.config.js
module.exports = (config, runtime) => {
config.plugins.push(
require('autoprefixer')({
/* ...options */
})
)
return config
}
H5 的自定义配置梳理: config/postcss.config.js
module.exports = (config, runtime) => {
config.plugins.concat([
require('postcss-write-svg')({
utf8: false
}),
require('postcss-px-to-viewport')({
viewportWidth: 750,
viewportHeight: 1334,
unitPrecision: 3,
viewportUnit: 'vw',
selectorBlackList: ['.nvw', '.hairlines'],
minPixelValue: 1,
mediaQuery: false
}),
require('postcss-viewport-units')()
])
return config
}
client 目录 => ~
| @
root 目录 => ~~
| @@
@import 'cssrecipes-defaults'; /* == @import "../node_modules/cssrecipes-defaults/index.css"; */
@import 'normalize.css'; /* == @import "../node_modules/normalize.css/normalize.css"; */
@import 'foo.css'; /* relative to css/ according to `from` option above */
@import 'bar.css' (min-width: 25em);
.element {
background: url('images/sprite.png');
}
<img src="~assets/lark.png" alt="">
<img src="/public/lark.png" alt="">
https://github.com/postcss/postcss-url > https://github.com/postcss/postcss-url
/* custom properties */
:root {
--fontSize: 1rem;
--mainColor: #12345678;
--highlightColor: hwb(190, 35%, 20%);
}
/* custom properties set & @apply rule */
:root {
--centered: {
display: flex;
align-items: center;
justify-content: center;
}
}
.centered {
@apply --centered;
}
/* custom media queries */
@custom-media --viewport-medium (width <= 50rem);
/* some var() & calc() */
body {
color: var(--mainColor);
font-size: var(--fontSize);
line-height: calc(var(--fontSize) * 1.5);
padding: calc((var(--fontSize) / 2) + 1px);
}
/* custom media query usage */
@media (--viewport-medium) {
body {
font-size: calc(var(--fontSize) * 1.2);
}
}
/* custom selectors */
@custom-selector :--heading h1, h2, h3, h4, h5, h6;
:--heading {
margin-top: 0;
}
/* image-set function */
.foo {
background-image: image-set(url(img/test.png) 1x, url(img/test-2x.png) 2x);
}
/* colors stuff */
a {
color: var(--highlightColor);
transition: color 1s; /* autoprefixed ! */
}
a:hover {
color: gray(255, 50%);
}
a:active {
color: rebeccapurple;
}
a:focus {
background-color: rgb(255 153 0 / 33%);
outline: 3px solid hsl(1turn 60% 50%);
}
a:any-link {
color: color(var(--highlightColor) blackness(+20%));
}
/* font stuff */
h2 {
font-variant-caps: small-caps;
}
table {
font-variant-numeric: lining-nums;
}
/* filters */
.blur {
filter: blur(4px);
}
.sepia {
filter: sepia(0.8);
}
/* overflow-wrap fallback */
body {
overflow-wrap: break-word;
}
/* attribute case insensitive */
[frame='hsides' i] {
border-style: solid none;
}
/* system-ui font-family */
body {
font-family: system-ui;
}
/*border-image*/
@svg 1px-border {
height: 2px;
@rect {
fill: var(--color, black);
width: 100%;
height: 50%;
}
}
.example {
border: 10px solid transparent;
border-image: svg(1px-border param(--color #00b1ff)) 2 2 stretch;
}
/*background-image*/
@svg square {
@rect {
fill: var(--color, black);
width: 100%;
height: 100%;
}
}
#example {
background: white svg(square param(--color #00b1ff));
}
基于 vw 方案, android 4.4 下 polyfill 处理:
require('viewport-units-buggyfill').init();
启用 polyfill 后, 可大胆使用 vw
vh
vmin
vmax
单位, 在基于设计稿开发时, 请确保设计图为 750 x 1334(否则自定义 config/postcss.config.js
), 在 css 中直接按设计图尺寸书写 px
单位, 预编译阶段会将 px
单位转换为 vw
, 如果需要忽略转换, 请添加 .nvw
class
项目开发贡献指南
fork => MR => review => merge
开发时建议测试驱动, 在 test
目录先写 case, 再写业务代码
$ npm run dev
TIPS 增加
DEBUG=inspect
环境变量(DEBUG=inspect fe dev
) 执行可以用 chrome devtools 来 debug node
# git commit 格式化
$ npm run commit
Commit changes
$ git add .
$ npm run commit
Bump version via npm
$ npm version patch
Generate CHANGELOG.md
$ npm run changelog
Commit CHANGELOG
$ npm run commit
Release new version
$ npm run release
# scp ...
then, github release.. etc.
DEBUG 方法:
FAQs
Front-End workflow & stack
We found that fe demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.