对于构建工具,相信大家并不陌生,熟悉webpack的人都知道,webpack的配置项非常庞大,有时想要找一个配置项就要花半天时间,所以有一部分人把目标投向了去年在构建工具类中排行冠军的零配置的parcel。
作为webpack的忠实粉丝,我并没有选择parcel这种简单构建工具,众所周知,比如一个需要传参才能执行某个事件的和一个不需要传参就可以执行某个事件的函数哪种灵活度更高。当然如果说需要传参的那个函数有一个默认的不需要传参的默认执行函数确实是更好,webpack以后的优化估计也会从这一点入手,无配置则有默认开发、打包执行函数,有配置则更改默认项。这样配置起来即轻松又灵活。
webpack的配置是一个多层级的对象,webpack在打包或者是开发的时候,会获取到该对象,放入一个函数作为一个参数,根据该参数的不同,执行不同的功能。由此可见webpack的灵活度是很高的,但若想配置好webpack,必须细化配置文件。所谓细化,其实就是拆分耦合。模块化各个配置项。
说到模块化就得先说说目录结构,好的项目具有清晰明了的目录结构,而这些目录结构其实也就是一个分为多层级的对象。如果想细化webpack配置,我们应该从目录结构上入手。
首先我们把业务配置提取为一个对象模块,做成自己想要的如表格一样简单、清晰、明了的模块。比如我们定义一个conf.js。
内容如下
module.exports={
"yourApps":['a','b','c'],//有a、b、c三个页面
"dev":{
"devStart":1,//从密码问题开始
"openBom":true//开发模式下是否打开新窗口
},
"pack":{
"chunkAll":false,//是否全部打包 关闭了就只打包yourApps[devStart]
"copy":{//打包完之后再进行一次复制,复制到比如thinkphp中css目录下,一般用在后台做路由的项目中
"css":"D:/wamp64/www/Public/Home/css"
}
},
"isSingle":true,//是否为单页应用
"asset":{//设置require资源路径
"base":"base",
"style":"base-style",//设为此路径后可以直接require('@style/a.less')即可使用src目录下base目录下base-style目录下的a.less文件
"js":'base-js',//同上
"tpl":'base-tpl'//同上
},
//加载的公共js文件,在其中引入的css会与之同名
/***********入口文件*****************/
"entry":{
"base":"src",//入口根目录
"html":"pages",
"js":"pages",
"baseJs":{
"base":'base-entry-js',
"names":["jquery-1.11.1.min","bootstrap","common","user-base"],//公共加载文件
},
"after":"index",//指定以yourApps中的某一项为目录名,输出after值的文件;如果为false则直接输出在根目录以yourApp中某一项为文件名的文件
},
/**********输出文件**********************/
"output":{
"base":"dist",//存放打包资源的根目录
"html":"html",
"js":"js",
"css":"css",
"images":"images"
},
//!0为 文件夹中包含index !1为 文件夹中直接输出html和js
"commonJs":false,//提取公共模块,false为不提取,字符串为提取公共模块名为该字符串
}
之所以不用json文件的原因是因为json不能注释。
其次,我们将开发环境的多种配置存放在develop中,如上图所示目录,我们如果想用webpack的热加载及express搭建路由。则可以引入两个中间件,webpack-dev-middleware和他的兄弟webpack-hot-middleware。
具体代码如下
process.env.NODE_ENV = 'dev';
/*************引入模块*****************/
const conf=require('../conf.js');
const glob = require('glob');
const express = require('express');
const webpack = require('webpack')
const path=require('path');
const dev = require('./base.js');
const plugins=require('../base/plugins/index.js');
var fs=require('fs');
/*************定义变量*****************/
var app = express();
var entry=dev.entry;
for(var key in entry){
entry[key]=[entry[key]];
entry[key].unshift('webpack-hot-middleware/client')
}
/*************执行方法*****************/
var compiler = webpack(dev);
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath:"/",
stats:{
colors:true,
chunks:false
}
});
var hotMiddleware =require("webpack-hot-middleware")(compiler,{
path:"/__webpack_hmr"
})
app.use(devMiddleware);
app.use(hotMiddleware);
app.get('/:viewname?',(req,res,next)=>{
var viewname = req.params.viewname
?(req.params.viewname + '.html')
: 'index.html';
var filepath = path.join(compiler.outputPath,'html', viewname);
// 使用webpack提供的outputFileSystem
compiler.outputFileSystem.readFile(filepath, function(err, result) {
if (err) {
// something error
return next(err);
}
res.set('content-type', 'text/html');
res.send(result);
res.end();
});
})
/*************输出接口*****************/
module.exports=app.listen(3000,function(err){
if(err){
console.log(err);
return;
}else{
console.log('Listening at http://localhost:' + 3000 + '\n')
}
});
引入的base文件为开发模式和打包所需要的公用文件,这时候我们建立的目录结构可以和需要的配置对象相符合,这样我们就能很快的找到相关配置项。我们可以把这种方法称为模块化配置对象。base中的目录结构如图所示:
一级对象对应一级目录,目录名与对象名保持一致。
base主目录下的index把这些文件夹的index导入进来作为对象的子分支,代码如下
/*************引入模块*****************/
const path=require('path');
const conf=require('../conf.js');
/*************定义变量*****************/
var output = conf.output;
var type=process.env.NODE_ENV;
var Aoutput={
path: path.resolve(__dirname, '../../'+output.base),
filename: output.js+"/[name].js"
};
/**************执行函数****************/
/**************输出接口****************/
module.exports={
entry: require('./entry'),
resolve:require('./resolve'),
output: Aoutput,
module: require('./module'),
plugins:require('./plugins')
}
这样依次类推,导入的对象中亦可建立子对象,需要的业务配置则从conf.js导入,最终达到用一个conf.js控制自己想要的配置。
而所有配置细化成不超过30行代码的小型文件。目录结构清晰明了,易于修改配置。
项目git地址 点击打开链接 https://github.com/jcyLite/webpack-project.git 这个项目中的jcy-webpack便是本人亲手配置的。可以在conf.js控制是多页应用还是单页应用