原理 使用 fs、glob 或 shelljs 等可以读取文件系统的库,解析出项目中所有的入口文件,然后动态生成 entry
和 HtmlWebpackPlugin
,这样就不要每次新增页面就手动修改 webpack entry。
使用 glob 实现
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 const getEntries = () => { let entry = {} let htmlWebpackPlugin = [] const entries = glob.sync('./src/pages/**/index.js' ) console .log('entries: ' , entries) entries.forEach((path ) => { const pageName = path.slice('./src/pages/' .length, -'/index.js' .length) entry[pageName] = path const html = new HtmlWebpackPlugin({ template: 'index.html' , filename: `${pageName} .html` , title: `${pageName} Page` , chunks: ['common' , pageName], }) htmlWebpackPlugin.push(html) }) return { entry, htmlWebpackPlugin } } const { entry, htmlWebpackPlugin } = getEntries()module .exports = { entry, plugins: [...htmlWebpackPlugin], }
使用 shelljs 实现 1 2 3 shelljs.ls(path.join(__dirname, '/src/**/*.page.js')).forEach((f) => { // ... })
示例 1
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 const shelljs = require('shelljs') /** * 通过约定的入口文件命名构建 webpack entry:`模块名.页面名` * 过程解析: * - filePath: `path/to/src/pages/animal/animal.page.js` * - filePathArr: `['path', 'to', 'src', 'pages', 'animal', 'animal.page.js']` * - fileName: `animal.page.js` * - pageName: `animal` * - entryFile: `./src/pages/animal/animal.page.js` * - template: `./src/pages/animal/index.html` * - entry: `{ animal: './src/pages/animal/animal.page.js' }` */ let entry = {} let htmlWebpackPlugin = [] const entries = shelljs.ls(path.join(__dirname, './src/pages/**/*.page.js')) entries.forEach(filePath => { const filePathArr = filePath.split('/') const fileName = _.last(filePathArr) const pageName = fileName.replace(/\.page.js$/, '') const srcPos = _.indexOf(filePathArr, 'src') const entryFile = `./${filePathArr.slice(srcPos).join('/')}` const template = entryFile.replace(fileName, `${pageName}.html`) entry[pageName] = entryFile const html = new HtmlWebpackPlugin({ template, // template: path.resolve(__dirname, `./src/pages/${pageName}/${pageName}.html`), filename: `${pageName}.html`, }) htmlWebpackPlugin.push(html) })
示例 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 const shelljs = require('shelljs') let entry = {} // 通过约定的入口文件命名构建webpack打包入口 // entry的name规则为:模块名.页面名 shelljs.ls(path.join(__dirname, '/source/**/*.page.js')).forEach((filePath) => { let filePathArr = filePath.split('/') let file = _.last(filePathArr) let page = file.replace(/\.page.js$/, '') // 从文件名中取出需要打包的文件的「页面名」 // 「模块名」取/source/module/,即source目录下一级目录名 let pos = _.indexOf(filePathArr, 'source') let mod = filePathArr.slice(pos + 1, pos + 2) // 防止直接将.page.js放到source目录中 if (/\.page.js$/.test(mod)) { console.log(err(`Please don't settle ${chalk.bold(file)} in folder source directly`)) return } entry[`${mod}.${page}`] = `./${filePathArr.slice(pos).join('/')}` })
使用 fs 实现 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 const fs = require ('fs' )const path = require ('path' )const MAIN_FILE = 'index.js' const TEMPLATE_FILE = 'index.html' const DIST_DIR = path.resolve(__dirname, '../dist' )const SRC_DIR = path.resolve(__dirname, '../src' )const PAGES_DIR = path.resolve(SRC_DIR, 'pages' )const DEV_MODE = process.env.NODE_ENV !== 'production' const getEntries = () => { let entrys = {} fs.readdirSync(PAGES_DIR).forEach((pageName ) => { const fullPagePath = path.resolve(PAGES_DIR, pageName) const fullFilePath = path.resolve(fullPagePath, MAIN_FILE) const status = fs.statSync(fullPagePath) if (status.isDirectory() && fs.existsSync(fullFilePath)) { entrys[pageName] = fullFilePath } }) return entrys } const getTemplates = (entrys ) => { let htmlWebpackPlugin = [] Object .keys(entrys).forEach((pageName ) => { const fullPagePath = path.resolve(PAGES_DIR, pageName) const fullFilePath = path.resolve(fullPagePath, TEMPLATE_FILE) const status = fs.statSync(fullPagePath) if (status.isDirectory() && fs.existsSync(fullFilePath)) { const html = new HtmlWebpackPlugin({ filename: `${pageName} .html` , template: fullFilePath, chunks: [pageName], title: `Page ${pageName} ` , }) htmlWebpackPlugin.push(html) } }) return htmlWebpackPlugin } const entrys = getEntries()const htmlWebpackPlugin = getTemplates(entrys)module .exports = { entry: entrys, plugins: [ ...htmlWebpackPlugin, ], }