漸進式配置webpack4單頁面和多頁面(三)

漸進式配置webpack4單頁面和多頁面

前言

使用包的版本css

webpack ->4.3.0
babel-loader ->8.0.5
npm ->6.4.1
webpack-cli ->3.3.1
複製代碼

每一個章節對應一個demohtml

構建多頁面配置

具體代碼參考demo12node

新建多頁面目錄

新建module文件,約定module目錄裏面每一個文件目錄必須有個html文件,還有一個與其名字相同的js文件做爲入口文件。 react

建立變量函數

build文件夾裏面的help.js裏面新建方法webpack

/**
 * @description: 遍歷文件夾裏面的全部文件
 * @param {array} [路徑地址]
 * @return: {文件名:文件地址}
 */
exports.getEntry = function getEntry(globPath) {
	var entries = {};
	if (typeof(globPath) != "object") {
			globPath = [globPath]
  }
	globPath.forEach((itemPath) => {
        // glob.sync 同步讀取
		glob.sync(itemPath).forEach(function(entry) {
				entries[entry.substring(13, entry.lastIndexOf('.'))] = entry; // 13表明'./src/module/'
		});
	});
	return entries;
};
複製代碼

引入多頁面文件

webpack.base.js裏面引入多頁面入口文件

var entries = help.getEntry(['./src/module/**/*.js']); // 得到入口js文件
console.log(entries);
/**
打印結果
{ 'demo/demo': './src/module/demo/demo.js',
  'test/test': './src/module/test/test.js' }
**/
複製代碼

添加到入口文件ios

entry:Object.assign({},{app:help.resolve('./app.js')},entries),
複製代碼

webpack.base.js裏面引入多頁面的html文件

function concatHtmlWebpackPlugin() {
  var entriesHtml = help.getEntry(['./src/module/**/*.html']);
  console.log(entriesHtml)
  /**
  打印結果
  { 'demo/demo': './src/module/demo/demo.html',
  'test/test': './src/module/test/test.html' }
  **/
  var res = [];
  for (var i in entriesHtml) {
    var html = entriesHtml[i];
    var obj = new htmlWebpackPlugin({
      filename: '.' + html.substring(html.lastIndexOf('/')),
      template: html, //html模板路徑
      inject: true, //容許插件修改哪些內容,包括head與body
      chunks: ['vendors',i],//i表明入口文件的key 指定注入某些入口文件
      minify: {
        // 壓縮 HTML 文件
        removeComments: isPord, // 移除 HTML 中的註釋
        collapseWhitespace: isPord, // 刪除空白符與換行符
        minifyCSS: isPord // 壓縮內聯 css
      },
    })
    res.push(obj)
  }
  return res
}
複製代碼

注入多頁面git

plugins:[
    
    new htmlWebpackPlugin({
      filename:'index.html',
      template:'./index.html',
      inject:true,
      chunks: ['vendors','app'], // 指定注入某些入口文件
      minify: {
        // 壓縮 HTML 文件
        removeComments: isPord, // 移除 HTML 中的註釋
        collapseWhitespace: isPord, // 刪除空白符與換行符
        minifyCSS: isPord // 壓縮內聯 css
      },
    })
  ].concat(concatHtmlWebpackPlugin())
複製代碼

splitChunks 進行默認配置

optimization: {
    splitChunks: {
      chunks: 'async',
      minSize: 30000,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      name: true,
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  },
複製代碼

運行命令github

npm run dev
複製代碼

能夠正常運行

多頁面拆包配置

具體代碼參考demo12web

每一個頁面的js文件引入各類包

src/module/demo/demo.js

import axios from 'axios';
import xlsx from 'xlsx';
import dropzone from 'dropzone';
import lodash from 'lodash';
console.log(lodash);
console.log(dropzone);
console.log(xlsx);
console.log(axios);
var s=document.createElement('div')
s.innerHTML='dome文件'
document.getElementById('app').appendChild(s);
複製代碼

引入了lodash、dropzone、xlsx、axios這4個包。npm

src/module/test/test.js

import echarts from 'echarts';
import xlsx from 'xlsx';
import dropzone from 'dropzone';
console.log(dropzone);
console.log(xlsx);
console.log(echarts)
var s=document.createElement('div')
s.innerHTML='test文件'
document.getElementById('app').appendChild(s);
複製代碼

引入了dropzone、xlsx、echarts這3個包。

app.js

import "regenerator-runtime/runtime";
import React from 'react';
import ReactDOM from 'react-dom';
import About from './src/view/about';
import Inbox from './src/view/inbox';
// import asyncComponent from './src/assets/js/AsyncComponent'
// const Inbox = asyncComponent(() => import( './src/view/inbox'));
// const About = asyncComponent(() => import( './src/view/about'));
import { BrowserRouter as Router, Switch, Redirect, Route, Link, HashRouter ,RouteChildren} from 'react-router-dom'
class App extends React.Component {
  render() {
    return (
      <div className="shopping-list">
      {this.props.children}
        <ul>
          <li><Link to="/about">About</Link></li>
          <li><Link to="/inbox">Inbox</Link></li>
        </ul>
      </div>
    );
  }
}

class Home extends React.Component {
  render() {
    return (
      <HashRouter>
        <Switch>
          <App>
            <Route path="/about" component={About} />
            <Route path="/inbox" component={Inbox} />
          </App>
        </Switch>
      </HashRouter>
    )
  }

}

ReactDOM.render(
  <Home />,
  document.getElementById('app')
);
複製代碼

引入了react、react-dom這2個包。

拆包分析

demo.js與test.js 有使用相同的包dropzone和xlsx。 app.js 只使用了 react和react-dom。

splitChunks 進行默認配置。

optimization: {
    splitChunks: {
      chunks: 'all',
      minSize: 30000,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      name: true,
      cacheGroups: {
        vendors: {
          name:'vendors',
          chunks: 'all',
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  },
複製代碼

直接打包

npm run build
複製代碼
npm run server
複製代碼

結果

首頁有很大的一個包。

test.html也同樣

demo.html也是同樣。

總結

說明引入的包都打包到一個js文件了,每一個多頁面都加載了多餘的包。因此默認配置不能很好的進行多頁面的拆包。

進行拆包優化配置

修改splitChunks代碼

optimization: {
    splitChunks: {
      chunks: 'all',
      minSize: 30000,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      name: true,
      cacheGroups: {
        reactVendors: { //reactVendors 來匹配react相關的包
          chunks: 'all',
          test: /(react|react-dom|react-dom-router)/,
          priority: 100,
          name: 'react',
        },
        commonVendors: { // commonVendors 來匹配xlsx和dropzone的包
          chunks: 'all',
          test: /(dropzone|xlsx)/,
          priority: 90,
          name: 'commonMode',
        },
        vendors: {
          name:'vendors',
          chunks: 'all',
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  },
複製代碼

多配置了commonVendors和reactVendors這兩個匹配項目。 試試 可不能夠。

npm run build
複製代碼

從打包的狀況 貌似能夠了。拆包成功。

可是打開頁面並無發現這些包有引入。

因此chunks沒有引入包全部須要去引入。

不一樣的入口文件引入不一樣的chunks

因此 app.js 這個入口文件須要引入 react 這個chunks。

new htmlWebpackPlugin({
      filename:'index.html',
      template:'./index.html',
      inject:true,
      chunks: ['vendors','app','react'],
      minify: {
        // 壓縮 HTML 文件
        removeComments: isPord, // 移除 HTML 中的註釋
        collapseWhitespace: isPord, // 刪除空白符與換行符
        minifyCSS: isPord // 壓縮內聯 css
      },
    })
  ].concat(concatHtmlWebpackPlugin())
複製代碼

多頁面須要引入 commonMode 這個chunks。

function concatHtmlWebpackPlugin() {
  var entriesHtml = help.getEntry(['./src/module/**/*.html']);
  console.log(entriesHtml)
  var res = [];
  for (var i in entriesHtml) {
    var html = entriesHtml[i];
    var obj = new htmlWebpackPlugin({
      filename: '.' + html.substring(html.lastIndexOf('/')),
      template: html, //html模板路徑
      inject: true, //容許插件修改哪些內容,包括head與body
      chunks: ['vendors',i,'commonMode'],//i表明入口文件的key
      minify: {
        // 壓縮 HTML 文件
        removeComments: isPord, // 移除 HTML 中的註釋
        collapseWhitespace: isPord, // 刪除空白符與換行符
        minifyCSS: isPord // 壓縮內聯 css
      },
    })
    res.push(obj)
  }
  return res
}
複製代碼

配置完成後。

頁面正常運行 而且拆包完成。
相關文章
相關標籤/搜索