Skip to content
This repository has been archived by the owner on Oct 2, 2022. It is now read-only.

nowa 2.0 #52

Open
tommytroylin opened this issue Jul 27, 2017 · 18 comments
Open

nowa 2.0 #52

tommytroylin opened this issue Jul 27, 2017 · 18 comments
Assignees

Comments

@tommytroylin
Copy link

tommytroylin commented Jul 27, 2017

Why

  • webpack@1 已被 废弃
  • 深度定制构建配置时,操作复杂甚至需要修改源码
  • 配置只有一套。普适性稍差
  • 没有插件 api。插件化不好开展

Solution

  • webpack 升级到 3.x
  • 从 cli 底层将现有配置与实现分离
  • 提供 config 的模板(默认配置,或者我们认为的 best practice),用户可以根据需求方便地复写、添加
  • 提供标准化的插件 api,规范调用方式

Target

简化项目文件:(1.0已经做到了)

  • 隐藏项目中的 webpack / eslint / babel 各种配置文件
  • 隐藏项目中的 npm script

抽离构建配置:(2.0的重点)

  • 高可定制化
  • 各业务线、用户使用独立 config (npm 包/文件)
  • 构建配置编写/修改方式需要简单高效
  • 协助提供定制、优化的 config

插件化:

  • nowa-eslint
  • nowa-proxy
  • nowa-cloud-builder
  • etc.

Pending Discussions

  • abc.json 上的 nowa 相关配置完全移除。使用插件方式生成abc.json 以支持云构建
  • 全局安装 vs 项目本地安装

由于 npm 到 5 了都没有实现基于全局的模式。意味着使用1.0全局的方式还是不太靠谱的。
考虑尽可能的使用本地安装的方式。
全局安装包 nowa 提供 nowa 命令。在项目目录下执行时 检查并运行项目下的 nowa 组件

  • 使用 ESNext + webpack 构建工作流
  • 使用 d.ts ts描述文件描述外露接口
  • 使用 airbnb 的编码规范
  • API 文档
  • 用户交互

Cases in Vision

有模板新项目:

  1. tnpm i nowa-cli nowa-init -g
  2. cd new-uxcore-component
  3. nowa init uxcore-template
  4. tnpm i
  5. nowa xxx

无模板项目(完美情况):

  1. tnpm i nowa-dev nowa-config-default -save-dev
  2. nowa xxx

构建配置编写:

nowa-config-xxxx index.js

// __dirname === project folder 
export const webpack = () => ({
  entry: ['./src/index'],
  // copy your webpack config here
});

export const eslint = async() => {

};

export const pluginName = {
  // ...
};

构建配置修改(部分修改):

.nowa.js

import { build as oldBuild } from 'nowa-config-default';
import { smart } from 'webpack-merge';
// export * from 'nowa-config-default';

export const build = {
  ...oldBuild,
  webpack: smart(oldBuild.webpack, { devtool: false }),
};
@gbk
Copy link
Contributor

gbk commented Jul 27, 2017

nowa-config-xxxx 里的一些常用配置,entry、output 等,最好还是能通过命令行参数加进去

@Jirapo
Copy link

Jirapo commented Jul 31, 2017

命令行的优先级 > .nowa.js
既然直接暴露了 export const build = merge(defaultWebpackConf, selfBuildCong), 那么原先的abc.json 里面的 buildvars / open / pages / mockapi / ... 放在哪里暴露?

nowa-config-xxxx index.js

export const server = {
 webpack: {
 // copy your webpack config here
},
src: 'src',
port: '3000',
open: true,
vars: {},
...
};

export const build = {
 webpack: {
 // copy your webpack config here
},
exportcss: true,
analyse: true,
dist: 'build',
groupVars: {},
...
};

export const eslint = {
};

export const UIPluginConfig = {
  // ...
};

.nowa.js

import * as nowa from 'nowa-config-default';
import { smart } from 'webpack-merge';

const config = {...nowa};
config.build = {
  webpack: smart(nowa.webpack, { devtool: false }),
};

config.server = {
...nowa.server,
open: false
}

export config;

@tommytroylin
Copy link
Author

@Jirapo
大部分的 abc.json 配置其实是个 alias。最终对应的是修改某个webpack 的配置。这种情况应该让用户自行修改。其目的是不引入多余的概念。
小部分的webpack 不相关的配置,会放到对应的插件配置里面去。

@Jirapo
Copy link

Jirapo commented Aug 1, 2017

nowa-config-default

export const build = () = {};
export const server = () = {};
export const eslint = {};
export const proxy =  {};
export const UIPlugin = {};
export const babelrc = {};
export const mockapi = {};
export const abc = {};

@tommytroylin
Copy link
Author

配置独立之后:

nowa-template:

  • 考虑下 模板的继承和重用 (1.0有模板功能,但模板之间相互独立无法实现复用)
  • 页面 / 组件 / 代码块 重用

@tommytroylin tommytroylin self-assigned this Aug 8, 2017
@tommytroylin
Copy link
Author

tommytroylin commented Aug 10, 2017

支持环境

一般情况下

nowa 的开发和持续集成 基于 Current 的 node 版本
nowa 的运行环境为 当前 LTS 版本以上

nowa 2.0

  • node 6 及以上
  • npm 3 及以上

安装

概述

推荐在每个项目下单独安装 nowa 以及配置

全局安装

名字暂定

  • nowa-cli

提供全局 nowa 命令、调用全局包、调用项目下的功能/插件

  • nowa-global-init

提供全局 nowa init 命令、下载并初始化项目

项目安装包 (名字暂定)

  • nowa

大包。包含所有可用插件

  • nowa-core

只包含构建/开发核心�

  • nowa-template
  • nowa-eslint
  • nowa-prettier

配置

  • nowa-config-default
  • nowa-config-web-react

模版

  • nowa-template-react
  • nowa-template-uxcore

内部包

  • nowa-core-util
  • nowa-core-config-resolver
  • ...

从带nowa配置的项目开始

使用

初始化项目

从项目模板初始化

使用此功能需要在全局安装 nowa-cli nowa-global-init

nowa init 命令提供了以下几个常见模板

  • react
  • uxcore
  • uxcore-component
  • ....

要从模板初始化一个项目,请执行nowa init [templateName]

  • 选择版本 / 分支
  • 回答一些参数 ()
  • 下载模板
  • 回答模板定义问题
  • 执行模板 hook
  • npm i

同时也支持 nowa init [templateURL]

手动初始化(有 config)

我们提供了多套默认设置以覆盖多数开发者的要求

  • 此页面 选择配置
  • 在项目下安装 nowa-core nowa-config-default
npm i -D nowa-core nowa-config-default

现在可以在项目中使用配置可用中的 nowa命令

手动初始化 (无 config)

如果默认配置无法满足您的需求,或者是项目本身已经有自己的 webpack 配置。也可可以使用 nowa 进行构建

创建/移动你的 webpack 配置到 nowa(.config).js

// TODO 示例图片

随后即可开始使用 nowa命令

开发

本地服务器开发

使用

可以通过 nowa server 命令来开启一个本地开发调试服务器。

请在项目根目录下执行。

nowa server

webpack 的构建输出文件将不会写到文件系统,而是缓存在内存中,在访问时直接输出。这样做可显著提高构建效率。

参数

// TODO 从 webpack-dev-server 选取参数

构建

可以通过 nowa build 命令进行构建。
请在项目根目录下执行。

nowa build --config default --dist .package

// TODO 从 webpack 选取参数

可配置多套构建方式,并通过第二参数进行调用

nowa build local
nowa build daily
nowa build prod
nowa build prod --output-path .package // 云构建

渐进配置

从已有配置开始

  1. 查看已有配置,并在 nowa.js 中对其部分作出覆盖或者修改
  2. 当配置过大 需要拆分时,可以使用 nowa 目录放置配置文件。使用 index.js 导出配置
  3. 当配置改动量大或者需要共享时,发布到npm
  4. 在新的项目npm i配置文件包
  5. 新项目的命令和构建行为与之前的项目相同

从空白项目开始

  1. 参考 手动初始化 章节 将webpack配置放置到合适位置
  2. 根据需求,完善配置、完善插件调用
  3. 当配置过大 需要拆分时,可以使用 nowa 目录放置配置文件。使用 index.js 导出配置
  4. 当需要共享配置时,整理nowa 依赖,编写配置文件包并发布到npm // TODO 不通过 npm 如何共享配置?)
  5. 在新的项目npm i配置文件包
  6. 新项目的命令和构建行为与之前的项目相同

插件

模板 nowa-template

  • 模板支持 可通过模板生成各种文件。包括页面、组件、云构建文件、配置文件等等

ESlint nowa-eslint

  • 格式化代码

Prettier nowa-prettier

  • 格式化代码

Mock nowa-mock-server

  • 启动 mock server

功能列表、状态

  • 初始化、模板(思考中)
  • 本地开发(webpack-dev-server)
  • 模块热替换(webpack-dev-server 和 config 共同完成)
  • 图片和svg(config中的 loader)
  • 远程调试、路由(webpack-dev-server)
  • 模拟数据(nowa-mock-server)
  • 环境变量 (definePlugin) (nowa-webpack插件形式提供)
  • 国际化(??)
  • 云构建(模板?)

TODO

  • 敲定配置文件格式
  • 实现命令的 alias,
  • 实现层级很深的常用配置。需要 alias 到根部 entry
  • 插件 API
  • init / template 构建 API,

@Jirapo
Copy link

Jirapo commented Aug 10, 2017

创建doc repo 放文档吧

@gbk
Copy link
Contributor

gbk commented Aug 11, 2017

  1. 建议 nowa-global-init 依赖到 nowa-cli 里面去,全局只装一个;
  2. nowa init 的时候,(通过命令行交互方式)提示用户并自动安装 server/build 相关功能模块和所需配置依赖(远程拉一份配置列表让用户选择?);
  3. 如果(一个非 nowa 脚手架)项目中还没安装 nowa 相关依赖,那么在目录下执行 nowa server/build 时,同样执行 2. 的操作;

这样对小白用户来说只需要安装一个东西,其他都是通过配置来的~。~完美

@Jirapo
Copy link

Jirapo commented Aug 11, 2017

nowa init 需要支持本地路径

@tommytroylin
Copy link
Author

@Jirapo

  1. 这边是随便写写的总结之后再整理好文档。
  2. 本地路径支持是需要加上,之前也有的

@gbk

  1. nowa-global-(xxx) 模块 拆出去也是为了插件化。不过合并到一起出个整合大包也是 ok 的

  2. nowa init 初始化相关功能模块。、这个应该是编写模板时在模板的这端做的。

    • 选择版本 / 分支 (nowa-init 从模板拉取) (可以在这里给几个不同版本的模板,包含不同依赖和配置)
    • 回答一些参数 (nowa-init 内置)
    • 下载模板
    • 回答模板定义问题
    • 执行模板 hook (也可以在这里这里模板根据回答的问题来生成依赖, //TODO 定义模板的 API。。。)
    • npm i
  3. 交互式这个逻辑可以有。但如果使用这个交互方式,这个的逻辑不太好放。。项目底下没有。全局的那个包只是提供个命令。加了判断逻辑就不够纯净了。。考虑下这种交互模式:

    1. 用户在空项目下执行 nowa [whateveryoulike] ,nowa-cli 报错说找不到项目底下的 nowa 功能包 (报错逻辑在 nowa-cli 肯定会有),并推荐在项目下安装 nowa 功能大包
    2. 用户安装 nowa 功能包, 并重新执行 nowa 命令
    3. nowa 功能包报错 说找不到可用的 config。给个链接贴到官方的 config 列表 让用户选择并安装
    4. 用户安装 config,问题解决

    这样交互虽然会多 x 层。但每层的判断逻辑会分离的比较清楚。

@wushanchao
Copy link

参考webpackbin.com ,如这个简洁好用即可。

@lpgray
Copy link

lpgray commented Aug 14, 2017

就一个要求,完全向下兼容即可

@tommytroylin
Copy link
Author

@wushanchao
这个类似于codepen吧。。我觉得他这个配置方式比较有意思。可以根据需要勾选loader这些。。其他的点没怎么看。。有遗漏的地方么?
这个 idea 收下了。可以考虑做 插件 / 引导页面帮助用户直接生成可用的配置。。

@lpgray
完全向下的兼容现在看上去是不太可能的。因为 webpack@1@3 也是大版本升级。。不仅仅是配置和 自身API 的变化。同时也需要对 被打包的代码 进行变更。这块就完全没办法做到完全向下兼容了。。。

发布2.0从我角度上是需要 catch up 最新的打包/优化方式。这个不仅仅是需要从构建配置这块入手。比如 code splittingtree shaking 这种优化是需要业务代码做调整的。
在产出2.0版本的同时在团队里面推配套的这种规范 / better practice。最终希望能够给线上的项目带来落到实处的 benefits ,而不仅仅是为了拓展性和代码简洁性的重构。

由于这个的改动量不少。做出来的话也只能从新的项目开始应用。。
老项目的话,等2.0功能稳定下来了之后我们会帮忙提供升级技术支持。。

@gbk
Copy link
Contributor

gbk commented Aug 14, 2017

@tommytroylin 向下兼容可以考虑提供一个升级包,这块我来搞吧

@tommytroylin
Copy link
Author

tommytroylin commented Sep 1, 2017

alpha 版本

安装

全局安装

npm i nowa-cli@next -g
  • nowa-cli

提供全局 nowa 命令、调用全局包、调用项目下的功能/插件

项目安装

npm i nowa-cli@next nowa-core@next nowa-build@next nowa-server@next -D

安装配置

react 项目

npm i nowa-config-react@next -D

使用

执行 nowa 以获取当前项目下可用的 nowa 组件列表

image

image

执行 nowa [命令] -h 来输出可用的所有配置

image

执行 nowa [命令] 来以默认配置(第一个配置包加上 ./nowa.js覆盖的部分)运行组件
image

执行 nowa [命令] [配置名] 来使用不同的配置 运行组件

配置编写及修改

配置包 demo

GitRepo

nowa-build alias 配置

README

nowa-server alias 配置

README

已知问题

  • 运行 nowa 命令时会输出最终配置。此为测试使用
  • 帮助信息现在的排列方式很奇怪
  • nowa-cli 必须需要在本地安装才能读取到配置和组件。之后会考虑解决(重新分包)
  • customFlag 这个option 暂不可用

TODO

  • nowa.js (alias 配置中支持调用组件中的自定义方法。)
    类似于:
build.addPlugin();
build.removePlugin();
build.addLoader();
build.replaceLoader();
build.removeLoader();
  • 配置如何将自己需要的参数暴露给 cli (babel-loader/preset-env target)
  • cli 运行时 hook

反馈

希望能够得到以下方面的意见。感谢

  • 命令行方式,是否需要引入交互式命令?
  • 配置的编写与修改是否方便

@tommytroylin
Copy link
Author

tommytroylin commented Sep 1, 2017

零配置启动一个 react 的 hello-world

  • 下载nowa2-test.zip
  • 解压
  • 进入目录 执行 npm i
  • 运行 npm run server 启动开发服务
  • 运行 npm run build 进行打包

@tommytroylin
Copy link
Author

@gbk @Jirapo

本周我自己使用 nowa@2 起了一个react typescript项目,发现了一些易用性的问题。我个人也思考并实施了下解决方案。在此讨论一下。。

如果有其他的意见也请一并贴出,现在大改动还来得及。。。
敲定之后,下周开始完善面向用户交互/报错/提醒之后 就会发布 beta / release candidate 版本了。。。

  • tsconfig.json 必须放置在 project 的根目录下。

下一步开发 init 组件。 可根据配置一键生成 .eslintrc abc.json 等等

  • 现有的配置方式缺少可自定义性。比如希望修改 babel-preset-env 的 配置 十分困难

之前考虑过通过注入 __customFlag 参数来处理一些类似情况。但单个的参数完全无法满足需求。
解决方案:新增一个选项配置和全局方法以提供自定义性

// 之前输出配置方式如下
exports const build = {
  context: __projroot, // nowa 挂载的全局数据
}; //  这里是 webpack config对象

新增之后

exports const buildOptions = { // 这个配置会传给 cli 用于输出帮助信息
  skipMinify: {
    default: false,
    describe: 'skip minify js files',
    type: 'boolean',
  },
  targetBrowsers: {
    default: 'ie >= 9',
    describe: 'https://babeljs.io/docs/plugins/preset-env/#optionstargets-browsers',
    type: 'string',
  },
};

exports const build = { // 之后此对象会递归过滤掉 undefined 值
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        options: {
          presets: [
            ['env', { targets: { browsers: __option('targetBrowsers') }, modules: false }],
          ],
        },
      },
    ],
  },
  plugins: [
    __option(({ skipMinify  }) => skipMinify ?  new MinifyPlugin() : undefined), // 全局方法名字暂定
  ],
};

而用户可以通过命令行参数和 alias进行配置

// nowa.js
export const nowa = { 
  build: {
    __options: { // 配置名字暂定
      targetBrowsers: 'chrome >= 50'
    },
 },
};
  • 配置需要执行一些回调。用以调用组件上的修改配置的方法

暂定在配置中读取

  • buildWillProcess 在 build 组件读取到所有 config 之后。处理(merge)config 之前
  • buildWillRun 在 build 组件运行之前(处理最终传给webpack/第三方工具的配置)
  • buildDidRun 在 build 组件执行完成之后调用

@tommytroylin
Copy link
Author

nowa 脚手架 / init 更改

  • 废弃掉之前的 name 命名方式。文件名、文件内容 均 统一使用 handlebars

    干掉 ejs 吧。。。语法太 XML 了。。

  • 可配置多项任务,根据命令 生成 项目源文件/配置文件/等等

  • 项目整体的模板沿用 template-xxxx,init项目时 直接下载并compile

  • 项目内的配置放在 config 包内或者 项目的 nowa 目录下

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants