閒來無事,學習一下怎麼用 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文件中分號必定要帶上