在上一节中,已经把基础环境搭建好了,这里就陆续实现各指令。首先我们从打包开始,毕竟能够打包编译js代码,这应该是一个脚手架工具最基础的功能。
webpack配置
webpack基础配置
新建文件src/webpack/config.com.js,该文件存放公用的webpack配置:
import jsLoader from '../babel/jsLoader'
import plugin from '../babel/plugin'
const path = require('path')
export default (props) => {
const {
entry = './index.js'
} = props
return {
entry,
output: {
path: path.join(process.cwd(), 'dist'), //输出路径
filename: 'bundle.js'
},
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json', '.vue'],
},
module: {
rules: [...jsLoader()] // 解析文件的各种loader
},
plugins: [...plugin()] // 配置一些常用的插件
}
}
新建文件src/webpack/config.prod.js,存放打包时的配置信息
import commonConfig from './config.com.js'
export default (pkg) => {
return {
mode: 'production', //设置开发模式
...commonConfig(pkg) //各个模式下的公共配置
}
}
配置loader
先配置babel-loader用以解析js代码
src/babel/jsLoader.js
export default () => {
return [
// babel-loader转义js https://webpack.docschina.org/loaders/babel-loader/#root
{
test: /\.m?js$/,
exclude: /node_modules/, //不用编译 node_modules
use: {
loader: require.resolve('babel-loader'),
options: {
presets: [require.resolve('@babel/preset-env')]
}
}
}
]
}
配置plugin
plugin是一些辅助插件, 暂时以配置ProgressPlugin为例,其作用是实时输出打包信息:
src/babel/plugin.js
import ProgressPlugin from "progress-bar-webpack-plugin"
export default () => {
return [new ProgressPlugin()] // 输出打包进度信息
}
打包配置
src/commander/build.js
import Webpack from 'webpack'
import webpackConfig from '../webpack/config.prod.js'
export default pkg => {
const compiler = Webpack(webpackConfig(pkg))
compiler.run((err, status) => {
if (err) {
console.log('build err', err)
process.exit(1)
}
})
}
入口文件配置
src/index.js
import build from './commanders/build'
...
// 自定义指令 build
program
.command('build')
.description('build program')
.action(() => {
build(config)
})
...
新建文件:demo/index.js,在此目录下执行
simple-cli build
就可以看到输出打包进度信息,并输出结果demo/dist/bundle.js。此时我们最基础的打包指令已经做好了。
优化
交互优化
现有的webpack关键配置,比如entry都是在工具内部写死的,但是一个合理的交互需要提给供用户自定义的能力。我们约定这些配置在用户项目的package.json文件的simple-cli字段下。
cli/src/index.js
...
const cwd = process.cwd()
// 定义默认值
let config = {
port: 8000,
entry: './index.js',
cwd: process.cwd()
}
const userPkgPath = `${cwd}/package.json` //用户目录下package.json文件路径
// 判断是否存在 package.json
if (fs.existsSync(userPkgPath)) {
let userConfig = require(userPkgPath).simple_cli || {}
// 优先使用用户自定义的配置
config = Object.assign(config, userConfig)
}
...
program
.command('build')
.description('build program')
.action(() => {
build(config)
})
打包优化
在生产环境下,我们都是遵循增量部署的原则。这就意味着,每次打包输出的js文件名称都是唯一的,webpack支持带哈希值的输出文件来满足这一要求。
更新src/webpack/config.com.js:
...
output: {
path: path.join(process.cwd(), 'dist'), // 输出路径
filename: 'bundle.[hash].js'
}
...
此时你会发现每次打包都会生成一个名称类似bundle.1ff2020b12189c7388ec.js的文件。
但是,这样又引入了另一个问题,你的dist目录下存储的文件越来越多,对于本地开发这显然没必要,保留最新的一份就够了。那么有没有一个办法在写入文件之前,先清空dist目录呢。
webpack告诉你,‘有’ 。 借助插件clean-webpack-plugin即可。
更新src/babel/plugin.js
import ProgressPlugin from "progress-bar-webpack-plugin"
import { CleanWebpackPlugin } from 'clean-webpack-plugin'
export default () => {
return [
new CleanWebpackPlugin(), // 清空output目录
new ProgressPlugin() // 输出打包进度信息
]
}
到这里一个简单的打包js指令已经完成了。其他指令的具体实现,努力更新中。
未完待续