本节我们将陆续实现start和init指令;
start指令
start指令,用于启动一个项目,其原理是基于webpackDevServer在本地启一个服务。
webpack配置
首先配置入口文件src/index.js
import start from './commanders/start.js'
...
program
.command('start')
.description('start a program')
.action(() => {
start(config)
})
...
src/commanders/start.js
import Webpack from "webpack";
import WebpackDevServer from "webpack-dev-server";
import path from 'path'
import getDevConfig from '../webpack/config.dev.js'
export default (config) => {
const { port = 8000, cwd } = config
const host = '0.0.0.0'
const webpackConfig = getDevConfig(config)
const devServer = {
port,
host,
open: true,
compress: true,
static: {
directory: path.join(cwd, 'dist'),
}
}
const complier = Webpack(webpackConfig)
const server = new WebpackDevServer(complier, devServer)
server.listen(port, host, () => {
console.log(`start server on http://localhost:${port}`)
})
}
src/webpack/config.dev.js
import commonConfig from './config.com.js'
export default (pkg) => {
return {
mode: 'development', //设置开发模式
...commonConfig(pkg) //各个模式下的公共配置
}
}
配置模板
对于一个前端项目,在浏览器打开是需要有一个html模板来承接的。webpack提供了一个插件HtmlWebpackPlugin,可以实现自动生成一个模板,并在模板内引入打包生成的所有的js文件。
配置src/babel/plugin.js
import HtmlWebpackPlugin from 'html-webpack-plugin'
...
export default () => {
return [
...
new HtmlWebpackPlugin(), // 自动生成html模板,并引入打包生成的所有js文件
]
}
此时已经可以在本地启项目了。
测试
修改demo/index.js文件
document.body.innerHTML = '<div>demo</div>'
demo目录下执行simple-cli start。会自动打开一个网页,显示demo文件。
init指令
作为一个完整的脚手架工具,除了start,build之外,init指令一样的重要,该指令的主要作用是:复制内置的模板到用户目录。
新建模板
首先建立一个react模板目录cli/templates/react:该目录下默认有两个文件index.js和package.json
index.js:
import React from 'react'
import { render } from 'react-dom'
render(
<div className="container">
<div>this is a react app</div>
</div>,
document.getElementById('root'),
)
package.json:
{
"name": "demo",
"version": "1.0.0",
"description": "a simple-cli init demo",
"scripts": {
"start": "simple-cli start",
"build": "simple-cli build"
},
"creator": "",
"license": "ISC",
"simple-cli": {
"port": 9000,
"entry": "./index"
},
"dependencies": {
"react": "^16.9.0",
"react-dom": "^16.9.0"
}
}
目前为止,我们的项目还不能解析jsx语法,我们更新src/babel/jsloader.js
...
{
"test": /\.(m?js|jsx)$/,
"exclude": /(node_modules|bower_components)/,
"use": {
loader: require.resolve('babel-loader'), // require.resolve很重要,在当前项目的node_modules中寻找对应的模块
options: {
presets: [
require.resolve('@babel/preset-env'),
require.resolve('@babel/preset-react') // 支持react
]
}
}
}
用同样的方法,可以配置其他对应的loader以支持less,stylus,css以及文件,图片等内容,这里不再累述,可以查看文末的源码。
此时任意新建一个目录,该目录下依次执行以下指令:
simple-init
npm install
simple-start
就会启动一个项目,并在打开一个默认的页面;
结语
至此,我们的脚手架的基本功能都已经实现了。其中包括init,start,build指令。可以满足日常所需,在生产环境,可以结合公司的技术栈,做相应的扩展。