傳統多頁應用的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配置來對舊項目進行重構。新人第一篇文章,有不對的地方望指出。_(:з」∠)_

相關文章
相關標籤/搜索