1

本文的webpack配置是基于vue-cli改良的,且面向有一定基础的人

初始准备工作

  1. 使用vue init webpack指令构建好一个初始的项目,删除无关的东西,更改一下项目目录如下
    并且把src static中的文件清空图片描述
  2. 删除package.json中无关的依赖

    - "vue": "^2.4.2"
    - "vue-loader": "^13.0.4",
    - "vue-style-loader": "^3.0.1",
    - "vue-template-compiler": "^2.4.2",
  3. 删除build/vue-loader.conf.js
  4. src中创建2个文件夹分别为index about,在其中再创建3个文件index.html index.css index.js
    目录结构为

     build
     config
     src
      |———— views
      |       |———— index
      |       |       |————— index.html
      |       |       |————— index.css
      |       |       |————— index.js
      |       |
      |       |———— index2
      |               |————— index.html
      |               |————— index.css
      |               |————— index.js
      |———— static      // 存放静态资源
      |———— lib         // 存放第三方库
    
    把每个页面当做一个模块,这样的模块化方便项目管理,一眼瞄过去也比较清晰

开始

  1. 更改webpack.base.conf.js 把与vue相关的配置删除

    module.exports = {
     resolve: {
     -  extensions: ['.js', '.vue', '.json'],
     +  extensions: ['.js', '.json'],
    alias: {
     -   'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
     },
     module: {
    rules: [
    -    {
    -      test: /\.vue$/,
    -      loader: 'vue-loader',
    -      options: vueLoaderConfig
    -    },
      {
        test: /\.js$/,
        loader: 'babel-loader',
    -      include: [resolve('src'), resolve('test')]
    +      include: [resolve('src')]
      },
     ........
    
  2. build/utils.js中,更改配置。不得不说utils.js中生成各种loader确实写的很棒,已经把所有的与css相关的loader涵盖进去,若要使用,只需要安装相关的loader即可

     if (options.extract) {
     return ExtractTextPlugin.extract({
       use: loaders,
     -     fallback: 'vue-style-loader'
     +     fallback: 'style-loader'
     })
     } else {
     -   return ['vue-style-loader'].concat(loaders)
     +   return ['style-loader'].concat(loaders)
     }

    我们不再需要vue-style-loader只需要普通的style-loader即可

  3. 既然是多页面,那么就肯定是有多个入口

    entry: {
      index: './src/index/index.js',
      about: './src/about/index.js'
    },

    这里科普一下,这里的entry路径是相对于webpack编译时的基础目录context(也就是package.json所在目录)。路径的详细解释可以参考这篇文章
    页面少的时候还ok,但是如果页面多起来的时候全部都要自己手动去配置确实是挺麻烦的。所以这里我们来写一段函数进行批量处理

    • 首先我们在build文件夹下新建文件pages.json用于存放页面的信息

      {
       "root": "./src",    //    页面存放的目录地址
       "pages": [          //    页面名, 打包生成的html,css,js文件也是这个名字
         "index",
         "about"
       ]
      }
    • 再在同个目录下创建pages.conf.js用来生成页面的路径

      
      var config = require('./pages.json')
      var root = config.root
      var pages = config.pages
      
      function genPagesDir() {
        var dirs = {}
        for (var i = 0; i < pages.length; i++) {
          var a = pages[i]
          dirs[a] = `${root}/${a}`
        }
        return dirs
      }
      
      module.exports = genPagesDir()
      
    • 跟着我们回到webpack.base.conf.js 增加生成入口配置的函数

      var pages = require('./pages.conf')
      
      ........
      
      function genEntries() {
       var entries = {}
       for (var key in pages) {
         entries[key] = `${pages[key]}/index.js`
       }
       return entries
      }
    • 并且把entry配置进行更改, 这样就大功告成

      entry: genEntries()
  4. 入口的配置完成之后,就要进行模板的配置,这里如果不了解html-webpack-plugin的,可以先去了解一下,单页应用只有一个页面所以模板就只有一个,那么如果是多页面应用,则可能会存在多个模板,多个模板就必须配置多个HtmlWebpackPlugin。说简单点就是,有n个页面,就要在plugins中写n

    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true
    }),

    所以这里就必须要再写一个批量生成的函数,和生成入口配置是一个道理的。

    var pages = require('./pages.conf')
    
    .......
    
    function genHtmlWebpackPlugin() {
     var arr = [];
     for (var key in pages) {
    arr.push(new HtmlWebpackPlugin({
      filename: `${key}.html`,               
      template: `${pages[key]}/index.html`,
      inject: true,
      chunks: [`${key}`]    //    chunk为该页面要包含的js文件
    }))
     }
     return arr;
    }
    
    module.exports = merge(baseWebpackConfig, {
     
     ....
     
     plugins: [
    ....
    -  new HtmlWebpackPlugin({
    -    filename: 'index.html',
    -    template: 'index.html',
    -    inject: true
    -  }),
    ....
    + ].concat(genHtmlWebpackPlugin())
    })
    

    filename是相对于output.publicPath, 在dev-server中则是相对于其assetsPublicPath, 保持这二者相同就是为了更方便的配置
    template则是相对于context(也就是上文提到的)
    chunks必须写,不然页面将会把所有打包后的js文件引入

  5. webpack.prod.conf.js的配置也是类似的,这里不再赘述,需要注意的是chunks需要包含vendor,manifest。 还有filename要用打包目录dist

     filename: `${config.build.assetsRoot}/${key}.html`
    
至此,所有的配置都完成了~
但是,在使用的时候发现,每次要增加一个新目录的时候都要先创建一个目录,然后再创建3个文件,再到pages.json中添加新增的页面。仔细想想好像还是挺麻烦的。那我们自个写个指令来自动实现这些功能吧!

懒人指令

  1. build中创建文件create.js
  2. package.json中添加指令
    "create": "node build/create.js"
  3. 开始码代码~

    • 我们的预想是通过npm run create filename指令完成上述一系列步骤,那么我们就要知道如何去在create.js中去读取这个filename。 其实这个参数就在变量process中,processnode的一个全局变量,这里不展开来讲,有兴趣的可以自己去了解。 我们可以试着打印一下process.argv的内容。
      create.js中增加以下代码,然后执行npm run create about, 查看输出

       var dirname = process.argv;
       console.log(dirname)

      图片描述
      可以看到process.argv中分别包含了指令的3个部分node,create.js,about 所以,process.argv[2]就是我们想要的dirname

    • 创建文件那就需要用到nodefs, 通过fs.mkdir来创建目录,再通过fs.writeFile来创建文件。当然我们还需要写一些异常处理的代码, 当指令没有输入filename或文件夹已存在时,进行提示,chalk可以让我们的cmd输出看起来更加美观一些。 下面为代码

      var fs = require('fs')
      var chalk = require('chalk')
      var root = require('./pages.json').root
      
      var dirname = process.argv[2]
      var path = `${root}/${dirname}`
      var htmlTemplate = `<!DOCTYPE html>
      <html lang="en">
      
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
          <title>title</title>
      </head>
      <body>
      </body>
      
      </html>`
         
      if (!dirname) {
         console.error(chalk.bgRed('Please input the dirname !!!\n'))
         return
       }
      if (fs.existsSync(path)) {
         console.error(chalk.bgRed('File is already exists !!!\n'))
         return
       }
      function throwErr (err) {
        if (err) {
          throw err
        }
      }
      
      fs.mkdir(path , (err) => {
         if (!err) {
      fs.writeFile(`${path}/index.html`, htmlTemplate, throwErr);
      fs.writeFile(`${path}/index.js`, '', throwErr);
      fs.writeFile(`${path}/index.css`, '', throwErr);
      console.log(chalk.bgGreen(' Create success.\n'));
        }
      })

      到这已经完成了文件的创建功能。

  • 接下来要写更新pages.json的代码,通过fs.readFilepages.json的内容读取进来,读取进来的是json字符串,那么使用JSON.parse即可将其转为对象,然后再往pages中增加新的内容,再然后使用JSON.stringify 将其转回字符串写回到文件中。大功告成

    function updatePages() {
      var path = 'build/pages.json'
      var rc = JSON.parse(fs.readFileSync(path, {encoding: 'utf-8'}))
      rc.pages = rc.pages.concat(dirname)
      var wc = JSON.stringify(rc)
      fs.writeFileSync(path, wc)
    }
    //    记得在创建完3个文件之后updatePages()进行调用
    

结束

至此所有的代码已写完了。之后就可以使用懒人指令进行创建文件了。只不过删除的时候不能自动更新,需要自己到pages.json中进行删除。

熟肉在这

之后还会再写多一片文章,通过使用这个webpack配置来对旧项目进行重构。
新人第一篇文章,有不对的地方望指出。_(:з」∠)_


Shiroyan
18 声望1 粉丝