webpack深入 ——使用篇(一)
webpack 作为现在最通用的一个JavaScript 打包器,其特点就是高度可配置,不过这也导致了webpack的配置相当繁琐与难以理解,有时候你配错一点东西就会造成整个打包失败,尤其是不同版本的webpack的配置还有些许不同,更是让人难受(ps.所以Parcel才会打着零配置Web应用打包工具的名头)。
这里本人想要深入理解一下webpack,从使用到源码。
webpack的使用主要有四个核心概念,接下来将挨个讲解。
入口(entry)
输出(output)
模块(module)或者loader
插件(plugins)
入口(entry)
入口起点,整个webpack打包的最初入口,从配置的这个或者这些文件开始,webpack开始查找对应的直接依赖和间接依赖,最终打包出对应的文件。
一般区分为单入口,多入口,根据文档结构读入口
单入口:
entry: './path/to/my/entry/file.js'
多入口:
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js',
pageThree: './src/pageThree/index.js'
}
根据文档结构读入口:
var relativeToRootPath = "src/entry";
function getEntry() {
var jsPath = path.resolve(relativeToRootPath);
var dirs = fs.readdirSync(jsPath);
var matchs = [], files = {};
dirs.forEach(function (item) {
var pathname = path.resolve(relativeToRootPath,item);
var stat = fs.lstatSync(pathname);
matchs = item.match(/(.+)\.js$/);
if(!stat.isDirectory()&&matchs){
files[matchs[1]] = [pathname];
}
else if(stat.isDirectory()) {
var dirs = fs.readdirSync(path.resolve(relativeToRootPath,pathname));
dirs.forEach(function (item) {
matchs = item.match(/(.+)\.js$/);
if (matchs) {
files[matchs[1]] =[path.resolve(relativeToRootPath,pathname, item)];
}
});
}
else{}
});
return files;
}
entry: getEntry()
输出(output)
output是一个对象,最简单的单文件的output:
output: {
filename: 'bundle.js',
path: '/home/proj/public/assets'
}
多入口文件,对应多输出文件,通过[]占位符,来让入口和出口对应
output: {
filename: '[name].js',
path: __dirname + '/dist'
}
output其实有许多配置项,有一些我们可能根本不会用到, 也有一些我们会常用到:
1.filename
最基本的配置项,必填,可以是写死的名称,路径,也可以用占位符来动态生成(多入口的情况下),比如[name].js或者[hash].js,[id].js
常用的占位符有四种,filename可以用这四种任意拼接。
[hash] 模块标识符(module identifier)的 hash
[chunkhash] chunk 内容的 hash
[name] 模块名称
[id] 模块标识符(module identifier)
2.chunkFilename
与filename类似,不过filename是对应有入口文件的,chunkFilename则是我们通过 CommonsChunkPlugin这类的插件生成的文件的输出名
3.library和libraryTarget
webpack默认会将文件打包,最终导出一个变量,当我们要用webpack打包一个组件或者模块时,我们更希望他能将导出的值赋给module.export。
libraryTarget指定我们打包后对象的导出方式,或者说暴露方式。
library就是暴露方式的对象名(必填)
libraryTarget有多种方式:
1.var(默认值):直接暴露为一个对象 var object = entry return _;
2.this:暴露为this的一个属性 this[‘library’]= entry return _;
3.window和global:暴露为window或者global的一个属性 window[‘library’]= entry return _
下面的这些值一般用于模块的开发中
1.commonjs2:暴露为module.exports 对象 module.exports = entry return _;,也就是我们es6默认支持的模块导出形式。
2.amd : 暴露为 AMD 模块 ,define(“MyLibrary”, [], function() {
// 此模块返回值,是入口 chunk 返回的值
});, 用于require.js这类的amd模块加载器3.umd:最常用也是最完善的模块导出,他会将你的 library 暴露为所有的模块定义下都可运行的方式,也就是你怎么用他都兼容,无论是amd还是commonjs,还是global都支持。
4.path
最终打包文件的输出的绝对路径
path: path.resolve(__dirname, 'dist')
5.publicPath
publicPath 也是一个非常重要的配置项,主要是在加载一些资源时对应的路径,也就是此输出目录对应的公开 URL。
如果是相对路径的话,则是相对于html页面来,比如“/”就是html下的目录。
当然正式环境下,我们可能会把一些静态资源都传到CDN上,这样我们就需要把这个publicPath配成我们cdn的路径,否则就找不到相应的资源了
默认值是一个空字符串 “”。