webpack分享

2018-10-31  本文已影响0人  思考的大腿

webpack分享

基本概念

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

模块

在模块化编程中,开发者将程序分解成离散功能块(discrete chunks of functionality),并称之为模块

每个模块具有比完整程序更小的接触面,使得校验、调试、测试轻而易举。 精心编写的模块提供了可靠的抽象和封装界限,使得应用程序中每个模块都具有条理清楚的设计和明确的目的。

Node.js 从最一开始就支持模块化编程。然而,在 web,模块化的支持正缓慢到来。在 web 存在多种支持 JavaScript 模块化的工具,这些工具各有优势和限制。webpack 基于从这些系统获得的经验教训,并将模块的概念应用于项目中的任何文件。

webpack 模块

对比 Node.js 模块,webpack模块能够以各种方式表达它们的依赖关系,几个例子如下:

ES2015 import 语句

CommonJS require() 语句

AMD define 和 require 语句

css/sass/less 文件中的 @import 语句

样式(url(...))或 HTML 文件img标签中的图片链接(image url)

核心概念

入口(entry)

输出(output)

loader

为什么需要loader? 因为webpack自身只处理JavaScript,不是js的东西需要先经过loader转换成js

插件(plugins)

loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。

常用的插件列表:

webpack.optimize.CommonsChunkPlugin

通过将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,便存到缓存中供后续使用。这个带来速度上的提升,因为浏览器会迅速将公共的代码从缓存中取出来,而不是每次访问一个新页面时,再去加载一个更大的文件。

extract-text-webpack-plugin

它会将所有的 入口chunk (entry chunks) 中的 require("style.css") 移动到分开的 css 文件。因此,你的样式不再内联到 javascript 里面,但会放到一个单独的 css 包文件 (styles.css)当中。 如果你的样式文件大小较大,这会更快,因为样式文件会跟 javascript 包并行加载。

html-webpack-plugin

生成一个html文件

webpack.HotModuleReplacementPlugin

模块热替换(HMR - Hot Module Replacement)功能会在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面。

open-browser-webpack-plugin

自动打开网页

webpack.DefinePlugin

允许创建一个在编译时可以配置的全局常量。这可能会对开发模式和发布模式的构建允许不同的行为非常有用

webpack.optimize.UglifyJsPlugin

压缩代码

zip-webpack-plugin

生成压缩文件

总结

Webpack在启动后会从Entry里配置的Module开始,递归解析Entry依赖的所有Module。每找到一个Module,就会根据Loader去找出对应的转换规则,对Module进行转换后,再解析出当前Module依赖的Module。这些模块会以Entry为单位进行分组,一个Entry以及其所有依赖的Module被分到一个组也就是一个Chunk。最后,Webpack会将所有的Chunk转换成文件输出,在整个流程中,Webpack会在恰当的时机执行Plugin里的逻辑。

entry

entry可以是 string, array, object

entry:'./app/entry'entry: ['./app/entry1','./app/entry2']entry: {entry1:'./app/entry1',entry2:'./app/entry2',}

生成的chunk名称:string和array,生成的Chunk的名称为main.js,object为键值对中的键名。

output

output: {//输出文件名称,如果有多个entry时可以根据内置的变量去动态生成,例如 '[name].js',提供的变量有id(chunk的唯一标识,从0开始),name(chunk的名称),hash(chunk的唯一标识的Hash值),chunkhash(chunk内容的Hash值),hash和chunkhash可以指定长度,例如[hash:8]代表8位Hash值,ExtractTextWebpackPlugin使用contenthash而不是chunkhash来代表Hash值,原因是因为,该插件提取出的内容是代码本身,并不是由一组模块组成的chunk。filename:'[name]-[hash]-bundle.js',//配置输出文件存放在本地的目录,必须为string的绝对路径,一般使用node的path模块path: path.resolve(__dirname,'dist'),//配置发布到线上的资源URL前缀publicPath:'https://cdn.example.com/assets/',}

module

module: {//配置模块读取和解析规则,类型为数组rules: [{//匹配规则test:/\.(js|jsx)$/,//指定包含的目录include: path.resolve(__dirname,'src'),//指定排除的目录exclude: path.resolve(__dirname,'node_modules'),use: ['babel-loader'],//重置顺序,pre放置最前,post放置最后enfore:'pre',    }],//让webpack忽略没有采用模块化的文件递归解析,(主要针对一些本身庞大但又没有采用模块化的库,例如jQuery、ChartJS),支持正则表达式和函数noParse:/jquery|chartjs/,//parse可以指定哪些模块的语法被解析,哪些不被解析,可以精确到语法层面,并非文件层面(区别于noParse)parse: {amd:false,//禁用AMDcommonjs:false,//禁用commonjs},//webpack在启动后会从入口模块出发找到所有依赖模块,我们可以根据需要修改修改匹配规则resolve: {//别名alias: {mobx:`${__dirname}/node_module/mobx`},//有的第三方模块会针对不同的环境提供几份代码,一般会放在package,json下,webpack会根据mainFields的配置去决定优先采用哪部分的代码。mainFields: ['browser','main'],//在导入语句没有添加后缀名时,会根据配置尝试添加后缀名查找文件,默认配置如下,例如require('./data'),会先去查找data.js找不到,再去找data.jsonextensions:  ['.js','.json'],//modules 配置webpack去哪些目录下寻找第三方模块,默认只会去node_modules模块下查找,也可以支持扩展modules: ['./src/components','node_modules'],//配置为true时,所有的导入语句都必须添加后缀。enforceExtension:true,//配置node_modules下的导入语句是否需要添加后缀,一般配合enforceExtension使用,因为很多第三方模块导入语句不会添加后缀,为了避免错误,在enforceExtension设为true时,需要将enforceModuleExtension设为falseenforceModuleExtension:false,    }}

plugin

plugin用于扩展Webpack的功能,数组中的每一项都是一个要使用的plugin的实例,几乎所有webpack无法直接实现的所有功能都可以在社区中找到plugin去解决。

plugin: [{newPlugin({//插件配置项})}]

devServer

devServer: {//启用模块热替换功能,配合插件 new webpack.HotModuleReplacementPlugin()使用,hot:true,//DevServer的实时预览功能依赖一个注入页面里的代理客户端,inline用于配置是否将这个代理客户端自动注入将运行在页面的Chunk里,默认自动注入。开启inline,devserver会在构建变化后的代码时通过代理客户端控制页面刷新。如果不开启,会以iframe的方式去运行要开发的网页,构建完变化的代码时,会通过刷新iframe来实现实时预览inline:true,//指定访问请求返回的文件historyApiFallback: {rewrites: [{from:/^\/user/,to:'/user.html'}]    },proxy: {'/h5/*': {target:'http://localhost:7601',pathRewrite:function(path){returnpath.replace('/h5/api','/h5');            }        },    },//在http响应中注入响应头header: {'X-foo':'bar'},//配置devserver服务监听的地址,默认本地,如果想要局域网内的其他设备访问,可以将host配置为 0.0.0.0host:'127.0.0.1',port:'8080',//配置是否关闭DNS绑定后的http请求的Host检查,一般配合host:0.0.0.0使用,可以让其他设备通过ip地址访问。disableHostCheck:false,//使用https协议,devserver会自动生成一份https证书https:true,//配置控制台输出的日志等('none', 'error', 'warning', 'info')clientLogLevel:'error',//配置是否启用Gzip压缩,默认不启用compress:true,//构建完毕使用默认浏览器自动打开网页open:true,}

上一篇下一篇

猜你喜欢

热点阅读