深入学习webpack(二)
在深入学习webpack(一)中,我通过一个例子介绍了webpack的基本使用方法,下面将更为系统的学习webpack的基本概念,对于一门技术的掌握我认为系统化还是很重要的,如果仅仅是一知半解,更为深入的地方了解不够,那么你就泯然众人矣。
webpack的核心概念主要有四个: entry(入口)、output(出口)、loaders(加载器)、plugins(插件)。 下面我将逐一介绍。
Entry
webpack会创建应用里所有依赖的图表,而最开始的图表就是所谓的入口文件。 入口文件会告诉webpack从何处开始并且根据依赖清楚如何打包。所以入口文件就是承接上下文的根文件或者说是你的app第一个使用的文件。
在webpack中我们在 webpack.config.js 中的entry选项里定义入口文件,最简单的定义方式如下:
module.exports = { entry: ‘./path/to/my/entry/file.js‘ };
这个非常容易理解,不再赘述。下面进行更为详细的介绍。
单一入口配置
webpack.config.js内容如下:
const config = { entry: ‘./path/to/my/entry/file.js‘ }; module.exports = config;
这和之前的配置是一样的,只是我们把导出的这个对象赋给了config对象之后才导出的。
说明: 这个语法是虽简单的语法,它是下面语法的简写形式。
const config = { entry: { main: ‘./path/to/my/entry/file.js‘ } };
What happens when you pass an array to
entry
? Passing an array of file paths to theentry
property creates what is known as a "multi-main entry". This is useful when you would like to inject multiple dependent files together and graph their dependencies into one "chunk".
当你希望快速建立一个单入口应用的webpack配置时,这是一个非常棒的选择。 然而,这个语法并没有太多的可扩展性。
注意:这里的main是可以替换的,并且换成任意的名称都是可以编译成功的,但是对于多入口文件,这里的名称就对应于html的名称了,比如两个页面,a.html和b.html,那么在entry中的两个键就是a和b了。
对象语法配置
webpack.config.js如下:
const config = { entry: { app: ‘./src/app.js‘, vendors: ‘./src/vendors.js‘ } };
对象语法可能显得冗杂一些,但是对于定义的入口文件和出口文件这是最具扩展性的方式。
"Scalable webpack configurations" are ones that can be reused and combined with other partial configurations. This is a popular technique used to separate concerns by environment, build target and runtime. They are then merged using specialized tools like webpack-merge.
Scenarios
下面的入口文件的使用是它们在生产环境中使用的例子:
独立的App和Vender入口
webpack.config.js如下所示:
const config = { entry: { app: ‘./src/app.js‘, vendors: ‘./src/vendors.js‘ } };
从表面来看,它告诉webpack从app.js和verdors.js两者同时开始(作为入口文件), 这些图表是完全独立的, 在单页面应用中这是非常常见的(除了verdors)。
多页面应用
const config = { entry: { pageOne: ‘./src/pageOne/index.js‘, pageTwo: ‘./src/pageTwo/index.js‘, pageThree: ‘./src/pageThree/index.js‘ } };
与单页面不同,对于多页面显然就有多个入口文件,这样配置的目的就是如此,即告诉webpack我们需要三个独立的依赖图表。
Output
即使你需要打包所有的文件到一个文件中你还是需要告诉webpack最终要打包到哪里,而这里的output属性就是告诉webpack如何处理打包文件的。
const path = require(‘path‘); module.exports = { entry: ‘./path/to/my/entry/file.js‘, output: { path: path.resolve(__dirname, ‘dist‘), filename: ‘my-first-webpack.bundle.js‘ } };
同样注意:这里的path时node的内置模块。
另外,出口文件的路径必须是绝对路径而不能是相对路径。
即我们使用了output.filename和output.path属性来将所有文件最终打包到path和filename对应的文件中去,这样,在html中,我们就可以应用这些文件了。
在entry中我们知道入口可以是多个,但是出口文件的配置确实指定的。
下面介绍一些常用的选项,即下面的属性是可以定义在output对象中的。
output.chunkFilename
不常用
output.crossOriginLoding
与跨域相关。
output.devtoolLineToLine
不常用。
output.filename
即指定出口文件的文件名,注意: 这里不能使用绝对路径,因为output.path选项决定了文件在磁盘上的位置,而filename仅仅是用来命名文件的。
(1)单入口
{ entry: ‘./src/app.js‘, output: { filename: ‘bundle.js‘, path: __dirname + ‘/build‘ } } // writes to disk: ./build/bundle.js
即对于单入口的文件,最终只会打包出一个文件。
(2) 多入口
当页面是多入口时,你应该使用替换法来确保每一个出口文件都有一个独一无二的名字。
其中[name]将会被打包出的文件名所代替。
[hash]将会被compilation(编译)所代替。
[chunkhash]将会被chunk的hash代替。举例如下所示:
{ entry: { app: ‘./src/app.js‘, search: ‘./src/search.js‘ }, output: { filename: ‘[name].js‘, path: __dirname + ‘/build‘ } } // writes to disk: ./build/app.js, ./build/search.js
注意: 这里的app和search对应的页面是app.html和search.html两个。
output.hotUpdateChunkFilename
不常用
output.hotUpdateFilename
不常用
output.hotUpdateMainFilename
不常用
output.jsonpFunction
不常用
output.library
不常用
output.libraryTarget
不常用
output.path
这必须是一个绝对路径。如下,config.js:
output: { path: "/home/proj/public/assets", publicPath: "/assets/" }
index.html:
<head> <link href="/assets/spinner.gif"/> </head>
更加复杂的例子是使用CDN。那么config如下:
output: { path: "/home/proj/cdn/assets/[hash]", publicPath: "http://cdn.example.com/assets/[hash]/" }
output.sourceMapFilename
不常用
努力的人,运气永远都不会太差!