使用 webpack 搭建多入口項目

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

項目github地址:https://github.com/xiaoliwang2016/webpack-demohtml

先來看一下目錄結構node

/admin、/home:模塊,能夠根據需求分,也能夠只須要一個模塊webpack

/htmlConfig:由於是多入口項目,所以須要一個配置文件來記錄多個入口的路徑,以及與模塊之間的層級關係,單入口文件僅須要定義一個入口,webpack會自動追蹤依賴關係,多入口須要定義多個,因此單獨存起來會好一些git

/webpack.config.js:webpack配置默認文件,能夠根據在開發環境和生成壞境分開github

/模塊/html:放置頁面文件web

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

/模塊/js:放置對應的js文件,名稱與html頁面一致json

/模塊/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文件中分號必定要帶上

相關文章
相關標籤/搜索