1. 程式人生 > >使用 webpack 搭建多入口專案

使用 webpack 搭建多入口專案

閒來無事,學習一下怎麼用 webpack 自定義多入口專案的打包

專案github地址:https://github.com/xiaoliwang2016/webpack-demo

先來看一下目錄結構

/admin、/home:模組,可以根據需求分,也可以只需要一個模組

/htmlConfig:因為是多入口專案,因此需要一個配置檔案來記錄多個入口的路徑,以及與模組之間的層級關係,單入口檔案僅需要定義一個入口,webpack會自動追蹤依賴關係,多入口需要定義多個,所以單獨存起來會好一些

/webpack.config.js:webpack配置預設檔案,可以根據在開發環境和生成壞境分開

/模組/html:放置頁面檔案

/模組/html/tpl:放置一些公用的模板

/模組/js:放置對應的js檔案,名稱與html頁面一致

/模組/css:放置樣式檔案

 

然後來看一下打包後的目錄

js檔案統一放置在/dist/js目錄,頁面檔案放在各自模組名稱對應的目錄下

看完最終效果我們來看一下webpack配置項


 

入口配置檔案

首先看一下前面提到的 htmlConfig.js 檔案

module.exports = {
    'admin' : [
        'index',
        'login'
    ],
    'home' : [
        'index'
    ]
}

很簡單,就是記錄了各個模組下的頁面的名稱,然後在webpack.config.js中拿去到這個配置項,遍歷打包這些頁面

 

webpack配置檔案

webpack會預設讀取根目錄下webpack.config.js檔案,通常可以將這個檔案拆分成dev和pro,這裡用作演示,沒有分開

const path = require('path')
const htmlConfig = require('./htmlConfig.js')
//生成html外掛
const htmlWebpackPlugin = require('html-webpack-plugin')
//抽離css外掛
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); var htmlWebpackPlugins = [] var entrys = {} for(var key in htmlConfig){ htmlConfig[key].forEach(item => { //生成 entry 物件中的 key 例如 { admin-login: './admin/login.html' } var k = key + '-' + item htmlWebpackPlugins.push(new htmlWebpackPlugin({ //template設定根據那個模板生成 template: `./src/${key}/html/${item}.html`, //生成html名稱 filename: `./${key}/${item}.html`, //chunks 設定需要引入的JS模組 chunks: [k], //自動引入js 可選:true(底部)/body/head inject: true, })) entrys[k] = `./src/${key}/js/${item}.js` }) } module.exports = { mode: 'production', entry: entrys, output: { path: path.resolve(__dirname, 'dist'), // name:對應entry的key ,chunkhash根據檔案進行MD5自動計算 filename: 'js/[name]-[chunkhash].js', //上線時可以使用 publicPath替換根路徑 // publicPath: 'http://cdn.com/' }, module:{ rules: [ { test: /\.js$/, //排除項 exclude: path.resolve(__dirname, 'node_modules'), //選擇項 include: path.resolve(__dirname, 'src'), loader: "babel-loader", //babel需要配合 babel-preset-env 一起使用 query: { "presets": ["env"] } }, { test: /\.css$/, //同一個檔案需要多個loader的情況下可以使用陣列,執行順序根據陣列從後往前執行 use: [ //使用MiniCssExtractPlugin.loader代替style-loader抽離css成單獨檔案 MiniCssExtractPlugin.loader, // 'style-loader', //每個loader可以有自己的引數,options欄位就是定義引數 { loader: 'css-loader', options: {importLoaders: 1}}, { loader: 'postcss-loader', options: { ident: 'postcss', //autoprefixer是postcss-loader的一個外掛,需要安裝,用於給css新增字首 plugins: [ require('autoprefixer')({ cascade: false }) ] } } ] }, { test: /\.tpl$/, loader: 'ejs-loader' } ] }, plugins: [ new MiniCssExtractPlugin({ filename: "css/[name].css", chunkFilename: "[id].css" }), ...htmlWebpackPlugins ] }

注意:這裡需要注意的是使用 loader 打包檔案時呼叫 loader 的順序時根據陣列從後往前,因此這裡處理css檔案的順序時:

postcss-loader --> css-loader --> style-loader

* postcss-loader是一個css後處理器,他提供很多外掛可以處理css檔案,例如css自動新增字首,壓縮等等

loader

js

webpack預設只會處理js檔案,因此如果有需要處理不同檔案時需要指定對應的loader

例如常用轉換js語法的loader:babel-loader

安裝:

npm install babel-loader --save-dev
npm install babel-preset-env --save-dev

然後需要在制定位置新增 presets 配置項

可以是 padkjson.js 或者 .babelrc 檔案 或者webpack.config.js中

 

模板

多入口檔案一般一個頁面對應一個js檔案,可以在js檔案中再次引入其他的模板(頁面),在通過loader解析最後插入到當前頁面

 

例如這裡的/admin/js/index.js對應的模板時/admin/html/index.html,然而還可以在index.js中引入一些其他的模板,例如引入admin/html/tpl/table.tpl,然後渲染插入到index.html中

在處理模板檔案時可以根據不同的模板設定不同的loader處理,這裡演示的是ejs的模板

<table class="table">
    <tr>
        <th>brand</th>
        <th>name</th>
        <th>price</th>
    </tr>
    <% for(var i = 0; i < data.length; i++) { %>
        <tr>
            <td><%= data[i].brand %></td>
            <td><%= data[i].name %></td>
            <td><%= data[i].price %></td>
        </tr>
    <% } %>
</table>

在webpack.config.js中配置loader

{
    test: /\.tpl$/,
    loader: 'ejs-loader'
}

在js檔案中可以直接通過import的放置引入該模板檔案

import table from '../html/layer/table.tpl'

ejs-loader處理完成後會返回一個函式(html-loader返回為字串),函式的引數為模板的變數,例如在admin/js/index.js檔案中引入模板然後插入到頁面

import '../css/index.css'
import table from '../html/layer/table.tpl'

document.querySelector('#table').innerHTML = table({
    data : [
        {brand: 'MI', name: 'MI6', price: 2999},
        {brand: 'iphone', name: 'iphoneX', price: 9999}
    ]
})

生成後頁面

 

樣式

 可以在js中直接通過import的方式引入

import '../css/index.css'

也可以在css中引入其他的css檔案

@import './common.css';

css檔案中分號一定要帶上