传统多页应用的webpack配置

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

初始准备工做

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

    - "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
    目录结构为vue

    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相关的配置删除node

    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便可webpack

    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便可git

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

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

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

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

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

      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配置来对旧项目进行重构。新人第一篇文章,有不对的地方望指出。_(:з」∠)_

相关文章
相关标签/搜索