webpack:多入口优化,根据命令行参数打包指定入口文件

2,864 阅读3分钟

前言

最近闲着没事干,于是把webpack官网文档又又又刷了一遍,结合公司的项目,做一次多页面项目的优化。

项目地址:gitee.com/linyongming…

多入口只是在entry配置多个入口,webpack是基于入口打包文件的,所以会去分别打包entry配置的每一个入口

多入口通常的配置如下:

const config = {  
entry: {
    pageOne: './src/pageOne/index.js',
    pageTwo: './src/pageTwo/index.js',
    pageThree: './src/pageThree/index.js'
  }};

常见多入口问题和优化

1.开发环境,打包了不需要的入口。

上图




这里还只是三个页面,如果是100个页面呢?后果很严重啊。那么,如何只打包我当前需要的入口呢?

最直接的方法是入口文件只写你需要的页面入口。比如我只需要pageOne的页面,那可以

 entry: {
    pageOne: './src/pageOne/index.js',
     // pageTwo: './src/pageTwo/index.js',
     // pageThree: './src/pageThree/index.js'
  }

但是这样的话,显得太麻烦了,如果可以通过命令解决这种问题就方便多了,比如 

npm run dev --file=xxx


通过带上 file=xxx 告诉webpack我想要打包哪个入口文件,如果不带上额外参数就全部打包,这样真是一举两得。

process.argv

process 对象是一个全局变量,它提供当前 Node.js 进程的有关信息,以及控制当前 Node.js 进程。 因为是全局变量,所以无需使用 require()。 

process.argv 属性返回一个数组,这个数组包含了启动Node.js进程时的命令行参数, 

 其中: 数组的第一个元素process.argv[0]——返回启动Node.js进程的可执行文件所在的绝对路径 第二个元素process.argv[1]——为当前执行的JavaScript文件路径 剩余的元素为其他命令行参数 

 例如: 输入命令:node scripts/build.js "web-runtime-cjs,web-server-renderer" 

 结果:

 console.log(process.argv[0]) // 打印 D:\nodeJs\node.exe 

console.log(process.argv[1]) // 打印 E:\Study_document\vue-resource\vue-dev\scripts\build.js 

console.log(process.argv[2]) // 打印 web-runtime-cjs,web-server-renderer 

这样的话,我们就能通过process.argv来获取到我们命令行添加的额外参数

function getCmdParas (name) {
  //process.argv 返回一个运行环境数组
  for (let key in process.argv) {
    if (process.argv[key].indexOf(`--${name}`) > -1) {
      return process.argv[key].split('=')[1]
    }  }
  return ''
}
const page = getCmdParas('page') || "**"const file = getCmdParas('file') || "**"
const pageUrl = `./src/${file}/main.js`

glob

用上面的方法我们获取到了 pageUrl ,它可能是具体的某个文件的路径,比如

./src/pageOne/main.js

也可能是一个匹配路径

./src/**/main.js
//表示匹配src下所有文件夹/main.js

而glob方法可以对输入的路径做匹配,返回匹配到的文件路径数组。

glob.sync为异步获取

用法:

glob.sync(pageUrl)  //['src/pageOne/main.js','src/pageTwo/main.js',.....]

那么我们利用这个可以动态的设置入口

const chunks = []
const entries = {}
const htmlWebpackPluginArray = []
glob.sync(pageUrl).forEach(path => {
  //path => ./src/pageOne/main.js
  const chunk = path.split('./src/')[1].split('/main.js')[0]
 // 得到每个文件的名字。 比如pageOne
  entries[chunk] = path
  chunks.push(chunk)
  const filename = chunk + '.html' // pageOne.html
  const htmlConf = {
    filename: filename,
    // template: path.replace(/.js/g, '.html'),
    inject: 'body',
    hash: true,
    chunks: ['commons', chunk]  }
  //此处利用 HtmlWebpackPlugin插件,生成每个入口对应的html
  htmlWebpackPluginArray.push(new HtmlWebpackPlugin(htmlConf))})

//这个方法的作用其实就是 获取shell 命令中的参数 
如输入 --page=xxxxxx,那么就可以获取到 
page=xxxxxx参数,
function getCmdParas (name) { 
 //process.argv 返回一个运行环境数组
  for (let key in process.argv) {
    if (process.argv[key].indexOf(`--${name}`) > -1) {
      return process.argv[key].split('=')[1]
    }  }  return ''}
const page = getCmdParas('page') || "**"
const file = getCmdParas('file') || "**"
const pageUrl = `./src/${file}/main.js`
const entries = {}
const htmlWebpackPluginArray = []
glob.sync(pageUrl).forEach(path => {  
//path => ./src/pageOne/main.js
  const chunk = path.split('./src/')[1].split('/main.js')[0]
 // 得到每个文件的名字。 比如pageOne  entries[chunk] = path
})

module.export={
  entry:entries
}

配置命令

最后一步就是配置你的命令

在package.json 的script中加入

"build": "npx webpack --config webpack.config.js --file=pageOne"

pageOne你可以修改为你想要打包的文件夹名称


自此大功告成。