闲来无事,学习一下怎么用 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文件中分号必定要带上