从零开始一个前端脚手架(三)

366 阅读1分钟

本节我们将陆续实现startinit指令;

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.jspackage.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指令。可以满足日常所需,在生产环境,可以结合公司的技术栈,做相应的扩展。

源码地址
从零开始一个前端脚手架(一)
从零开始一个前端脚手架(二)
从零开始一个前端脚手架(四)