在构建企业级前端框架 Elpis 的过程中,我们不仅关注功能的完整性与可扩展性,也致力于将其模块化、标准化,最终以 NPM 包的形式发布,供其他项目复用。本文将详细介绍如何将 Elpis 框架从业务代码中抽离,并封装为一个可发布的 NPM 包。
第一步:抽离业务代码
在框架开发初期,为了验证功能,我们嵌入了部分业务逻辑。要将 Elpis 独立成 NPM 包,首先需要将这些业务代码剥离,确保框架本身保持纯粹。
package.json 基本结构
json
{
"name": "elpis-core",
"version": "1.0.0",
"description": "企业级前端框架",
"main": "index.js",
"repository": {
"type": "git",
"url": "https://github.com/your-repo/elpis-core.git"
},
"author": "Your Name",
"license": "ISC"
}
第二步:本地包调试
在正式发布前,我们使用 npm link
将 Elpis 框架软链到本地项目中,便于调试和验证抽离效果。
bash
cd elpis-core
npm link
cd your-business-project
npm link elpis-core
第三步:核心模块抽离
Loader 路径配置
为了兼容业务项目与框架本身的资源加载,我们在 loader 中添加双路径支持:
ini
const elpisPath = path.resolve(__dirname, '../../app/loader');
const businessPath = path.resolve(process.cwd(), './app/loader');
通过封装挂载逻辑,将两者统一加载。
第四步:Webpack 配置抽离与融合
我们将开发与生产环境的打包逻辑封装为统一接口:
ini
function frontendBuild(env) {
if (env === 'local') {
FEBuildDev();
} else if (env === 'production') {
FEBuildProd();
}
}
动态构建入口文件
使用 glob
动态读取 Elpis 与业务项目的页面入口:
ini
const elpisEntryList = path.resolve(__dirname, '../../pages/**/entry.*.js');
const businessEntryList = path.resolve(process.cwd(), './app/pages/**/entry.*.js');
统一处理:
less
function handlerFile(file, entries, htmlWebpackPluginList) {
const entryName = path.basename(file, '.js');
entries[entryName] = file;
htmlWebpackPluginList.push(new HtmlWebpackPlugin({
filename: path.resolve(process.cwd(), './app/public/dist', `${entryName}.tpl`),
template: path.resolve(__dirname, '../../view/entry.tpl'),
chunks: [entryName]
}));
}
合并配置
ini
let businessWebpackConfig = {};
try {
businessWebpackConfig = require(`${process.cwd()}/app/webpack.config.js`);
} catch (e) {}
module.exports = merge.smart(defaultElpisWebpackConfig, businessWebpackConfig);
第五步:Loader 与别名配置
为避免解析错误,所有 loader 使用 require.resolve
:
css
{
test: /.vue$/,
use: {
loader: require.resolve('vue-loader')
}
}
针对业务与框架 JS 文件分别处理:
css
{
test: /.js$/,
include: [
path.resolve(__dirname, '../../pages'),
path.resolve(process.cwd(), './app/pages')
],
use: {
loader: require.resolve('babel-loader')
}
}
别名规范化
将框架与业务模块区分命名,例如:
$elpisCurl
:框架模块businessComponentConfig
:业务组件配置
第六步:公共组件扩展机制
为了支持业务项目扩展公共组件,我们提供健壮的别名配置:
ini
const aliasMap = {};
const blankModulePath = path.resolve(__dirname, '../libs/blank.js');
const businessComponentConfigPath = path.resolve(process.cwd(), './app/components/config.js');
aliasMap['$businessComponentConfig'] = fs.existsSync(businessComponentConfigPath)
? businessComponentConfigPath
: blankModulePath;
最终合并配置:
javascript
import BusinessComponentConfig from '$businessComponentConfig';
export default {
...componentConfig,
...BusinessComponentConfig
};
第七步:发布 NPM 包
确保使用官方源并登录:
arduino
npm config set registry https://registry.npmjs.org/
npm login
npm whoami
npm publish --access public
总结
一个成熟的 NPM 包不仅仅是代码的集合,更是开发者与使用者之间的契约。Elpis 的抽离过程强调了以下几点:
- 模块化设计与业务解耦
- 灵活的打包与配置机制
- 健壮的扩展能力与别名规范
- 清晰的文档与使用指南
未来,我们将继续优化 Elpis 的架构,提升其在企业级应用中的适配性与开发体验。