首先理清脚手架需要帮我们优化哪些步骤,通过对xxx项目分析,得出脚手架需要帮助我们处理好以下问题
- js的打包,es6语法支持,模块引用问题,按需引入问题,提高业务开发效率和兼容性问题
- sass文件的打包
- 自动化编译
- 区分js css的打包配置,各司其职
安装模块
1 2 3 4 5 6 7 8 9 10 11
| # babel npm i -D @babel/core @babel/cli core-js@3 @babel/preset-env # sass npm i -D mini-css-extract-plugin sass node-sass autoprefixer # webpack npm i -D webpack webpack-cli webpack-dev-server css-loader sass-loader babel-loader postcss-loader # shell npm i -D/-g shelljs chalk onchange cross-env
|
配置文件
build 文件夹存放 webpack 配置
1 2 3 4
| build ├── common.js ├── webpack.prod.css.js └── webpack.prod.es.js
|
公共方法 common.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| const fs = require('fs')
const checkFile = (file, { reg, dirReg, repDir }, getConf, path) => { if(file.match(dirReg) && file.match(reg)){ let key = file.replace(reg, '').replace(repDir, '') const conf = getConf(key, file) console.log(`======== 打包 ${key} ${file} ========`) path.push(conf) } }
const getFiles = (path, callback) => { const files = fs.readdirSync(path) files.map(file => { if(!callback(`${path}/${file}`, path)){ let exists = true let newPath = `${path}/${file}` try { fs.readdirSync(newPath) } catch (error) { exists = false } if(exists) getFiles(newPath, callback) } }) }
module.exports = { checkFile, getFiles }
|
js配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| const path = require('path')
const { checkFile, getFiles } = require('./common.js')
const SourceMapDevToolPlugin = require('webpack').SourceMapDevToolPlugin
const needChange = process.env.change || ''
const jsPath = []
const dirName = 'wp-js'
const jsReg = /\.js$/
const dir = `./${dirName}`
const repDir = `./${dirName}/`
const dirReg = new RegExp(dirName,'ig')
const options = { dir, reg: jsReg, dirName, repDir, dirReg }
const getConf = (key, file) => { return { mode: "production", entry:{ [key]: file }, output:{ filename: '[name].js', path: path.resolve('js') }, module:{ rules:[ { test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ } ] }, plugins: [ new SourceMapDevToolPlugin({ filename: '.map/[file].map', }) ] } } if(needChange === 'all') { getFiles(options.dir, (file) => { checkFile(file, options, getConf, jsPath) }) }else{ checkFile(`./${needChange}`,options, getConf, jsPath) } module.exports = jsPath.length ? jsPath : {}
|
处理scss文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
const path = require('path')
const { checkFile, getFiles } = require('./common.js')
const SourceMapDevToolPlugin = require('webpack').SourceMapDevToolPlugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const needChange = process.env.change || ''
const dirName = 'wp-css'
const scssReg = /\.scss$/
const dir = `./${dirName}`
const repDir = `./${dirName}/` const dirReg = new RegExp(dirName,'ig')
const options = { dir, reg: scssReg, dirName, repDir, dirReg }
const sassLoaders = [ MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader' ]
const scssPath = []
const getConf = (key, file) => { return { mode: "production", entry:{ [key]: file }, output:{ filename: '.empty.index.js', path: path.resolve('css') }, module:{ rules:[ { test: /\.scss$/, use: sassLoaders } ] }, plugins: [ new SourceMapDevToolPlugin({ filename: '.map/[file].map', }), new MiniCssExtractPlugin({ filename: `/[name].css` }) ] } } if(needChange === 'all') { getFiles(options.dir, (file) => { checkFile(file, options, getConf, scssPath) }) }else{ checkFile(`./${needChange}`,options, getConf, scssPath) } module.exports = scssPath.length ? scssPath : {}
|
从开发文件夹 wp-js 输出到 js 文件夹,wp-css 输出到 css 文件夹,通过 onchange 模块对项目进行监听,做自动化打包,创建一个 change.js 来作为变动后的脚本,判断是否执行打包操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const { rm, cp, mkdir, exec, echo, env } = require('shelljs') const chalk = require('chalk')
let change = process.env.change || '' console.log(chalk.green('==== 执行change脚本 ====')) console.log(chalk.red(`==== 变更${change} ====`))
if(change.match('wp-js')){ exec(`cross-env change=${change} npm run build:js -s`) }else if(change.match('wp-css')){ exec(`cross-env change=${change} npm run build:css -s`) } console.log(chalk.green('==== 打包结束 ===='))
|
babel 配置
1 2 3 4 5 6 7 8 9 10
| { "presets":[ ["@babel/preset-env", { "modules": false, }], ], "plugins": [ ["@babel/plugin-proposal-object-rest-spread", { "loose": true }], ] }
|
postcss 配置
1 2 3 4 5
| module.exports = { plugins: [ require('autoprefixer')({}) ] }
|
配置可执行命令,package.json 中的 scripts
1 2 3 4 5 6 7 8 9 10 11 12 13
| { "scripts": { "build:js": "webpack --config build/webpack.prod.es.js", "build:all:js": "cross-env change='all' npm run build:js", "build:css": "webpack --config build/webpack.prod.css.js", "build:all:css": "cross-env change='all' npm run build:css", "build:all": "cross-env change='all' npm run build:css & cross-env change='all' npm run build:js", "watch": "onchange --await-write-finish 500 -i \"**/*.js\" \"**/*.scss\" -e './js/**/*.js' './css/**/*.scss' -- cross-env change='{{changed}}' node scripts/change.js", "watch:js": "onchange --await-write-finish 500 -i \"**/*.js\" -e './js/**/*.js' -- cross-env change='{{changed}}' node scripts/change.js", "watch:css": "onchange --await-write-finish 500 -i \"**/*.scss\" -e './css/**/*.scss' -- cross-env change='{{changed}}' node scripts/change.js", "postbuild:css": "rm -rf css/.empty.index.js & rm -rf css/.map/.empty.index.js.map" }, }
|
运行 npm run watch 进行开发
wp-js => js
- 支持 es6 语法,es6 api 需要到 es.api 文件夹引入对应api(不然安卓4.4不支持)
- 支持 import export 语法
- 支持混淆压缩
- 支持 tree shaking
wp-css => css
- 支持 scss 文件处理