我们在用webpack构建项目的时候,有两种配置打包文件的方式:

  1. import或者require :a-loader!b-loader!.././static/dog.png(打包某一个文件)
  2. 配置webpack.config.js文件的module.rules(打包某一类的文件)

  针对于以上的第二种方式我贴下我之前一篇博客中的配置 Vue动态注册异步组件(非同一个工程的组件)

var path = require('path')
var webpack = require('webpack') module.exports = {
entry: process.NODE_ENV === 'development' ? './src/main.js' : './src/component/index.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'async-component.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
},
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
],
},
{
test: /\.sass$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader?indentedSyntax'
],
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
// Since sass-loader (weirdly) has SCSS as its default parse mode, we map
// the "scss" and "sass" values for the lang attribute to the right configs here.
// other preprocessors should work out of the box, no loader config like this necessary.
'scss': [
'vue-style-loader',
'css-loader',
'sass-loader'
],
'sass': [
'vue-style-loader',
'css-loader',
'sass-loader?indentedSyntax'
]
}
// other vue-loader options go here
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json']
},
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true
},
performance: {
hints: false
},
devtool: '#eval-source-map'
} if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
// new webpack.optimize.UglifyJsPlugin({
// sourceMap: true,
// compress: {
// warnings: false
// }
// }),
new webpack.LoaderOptionsPlugin({
minimize: false
})
])
}

  对单文件打包的方式的loader被称为行内(inline)loader;对于rules中的loader,webpack还定义了一个属性 enforce,可取值有 pre(为pre loader)、post(为post loader),如果没有值则为(normal loader)。所以loader在webpack中有4种:normal,inline,pre,post

  贴下官方源码地址 :Loader Type

for (const r of result) {
if (r.type === "use") {
if (r.enforce === "post" && !noPrePostAutoLoaders) {
useLoadersPost.push(r.value);
} else if (
r.enforce === "pre" &&
!noPreAutoLoaders &&
!noPrePostAutoLoaders
) {
useLoadersPre.push(r.value);
} else if (
!r.enforce &&
!noAutoLoaders &&
!noPrePostAutoLoaders
) {
useLoaders.push(r.value);
}
} else if (
typeof r.value === "object" &&
r.value !== null &&
typeof settings[r.type] === "object" &&
settings[r.type] !== null
) {
settings[r.type] = cachedCleverMerge(settings[r.type], r.value);
} else {
settings[r.type] = r.value;
}
}

  所有的loader的执行顺序都有两个阶段:pitching和normal阶段,类似于js中的事件冒泡、捕获阶段(有人嫌官方的词描述的比较晦涩,修改为loader的标记阶段(mark stage)和执行阶段(execution/run stage))。

  对于第二种方式的解释:webpack 官方解释

  1. Pitching阶段: post,inline,normal,pre
  2. Normal阶段:pre,normal,inline,post

  我看有大神的解释如下:(很好理解)

It's like the two phases of event bubbling...

a!b!c!resource

pitch a
  pitch b
    pitch c
      read file resource (adds resource to dependencies)
    run c
  run b
run a
When a loader return something in the pitch phase the process continues with the normal phase of the next loader... Example: pitch a
  pitch b (returns something)
run a

  对应的方式1解析loader的源码

let elements = requestWithoutMatchResource
.replace(/^-?!+/, "")
.replace(/!!+/g, "!")
.split("!");

  对应的方式2解析loader的源码

const result = this.ruleSet.exec({
resource: resourcePath,
realResource:
matchResource !== undefined
? resource.replace(/\?.*/, "")
: resourcePath,
resourceQuery,
issuer: contextInfo.issuer,
compiler: contextInfo.compiler
});

  那么问题来了,如果我们采用了两种解析loader的方式,他们的执行是什么样的呢?答案是inline loader优先级高于config配置文件中的loader:源码

  webpack使用了neo-async库(用来提供js异步编程的工具库)来解析loader模块,解析inline loader的源码

解析config loader的源码

  webpack官方文档推荐不适用inline loader,最好用在配置文件中使用loader(注意:loader处理的代码中是含有inline loader的)。另外,在特殊情况下我我们可以在inline loader间接改变loader的执行顺序(禁止某些另外3种loader),比如在我们的自己公司某个同事的不是很规范的js库在引入的时候需要禁止掉eslint-loader对其进行处理

  1. 加入 !   前缀禁用配置文件中的普通loader,比如:require("!raw!./script.coffee")
  2. 加入 !!  前缀禁用配置文件中所有的loader,比如:require("!!raw!./script.coffee")
  3. 加入 -!  前缀禁用配置文件中的pre loader和普通loader,但是不包括post loader,比如:require("!!raw!./script.coffee")

  关于loader的禁用,webpack官方的建议是:除非从另一个loader处理生成的,一般不建议主动使用

  1. pre loader 配置:图片压缩
  2. 普通loader 配置:coffee-script转换
  3. inline loader 配置:bundle loader
  4. post loader 配置: 代码覆盖率工具

Webpack Loader种类以及执行顺序的更多相关文章

  1. 如何开发webpack loader

    关于webpack 作为近段时间风头正盛的打包工具,webpack基本占领了前端圈.相信你都不好意思说不知道webpack. 有兴趣的同学可以参考下我很早之前的webpack简介 . 确实webpac ...

  2. 手把手教你撸一个 Webpack Loader

    文:小 boy(沪江网校Web前端工程师) 本文原创,转载请注明作者及出处 经常逛 webpack 官网的同学应该会很眼熟上面的图.正如它宣传的一样,webpack 能把左侧各种类型的文件(webpa ...

  3. webpack loader实现

    正值前端组件化开发时代,那么必然离不开目前最火的构建工具--webpack(grunt,gulp等暂且不谈).说到这里,刚好有几个问题: 为什么运行打包命令之后,.vue 文件可以转成 .js 文件 ...

  4. 揭秘webpack loader

    前言 Loader(加载器) 是 webpack 的核心之一.它用于将不同类型的文件转换为 webpack 可识别的模块.本文将尝试深入探索 webpack 中的 loader,揭秘它的工作原理,以及 ...

  5. webpack loader & pulgin

    webpack loader & plugin https://webpack.js.org/concepts/loaders/ https://webpack.js.org/concepts ...

  6. 浅析js的执行顺序

    javascript是一种描述型的脚本语言,是一种解析语言,由浏览器动态解析,不同种类的浏览器不同版本的浏览器对于js的解析有着微小的差别,不同浏览器的js解析引擎效率也有高低,下面来给大家分析一下j ...

  7. (转)java for循环的执行顺序和几种常用写法

    算是温习吧.问题比较基础,但是也比较重要.(虽然是C,但是很经典) for循环可以说在每个程序中都少不了的,语句头包括三个部分:初始化,判读条件,一个表达式. 但是这三个部分的执行顺序是什么,这是我们 ...

  8. python接口自动化(二十二)--unittest执行顺序隐藏的坑(详解)

    简介 大多数的初学者在使用 unittest 框架时候,不清楚用例的执行顺序到底是怎样的.对测试类里面的类和方法分不清楚,不知道什么时候执行,什么时候不执行.虽然或许通过代码实现了,也是稀里糊涂的一知 ...

  9. 转:Filter的执行顺序与实例

    转:http://www.cnblogs.com/Fskjb/archive/2010/03/27/1698448.html Filter的执行顺序与实例 Filter介绍 Filter可认为是Ser ...

随机推荐

  1. jq 获取各个元素的宽度高度的方法

    JS获取各种宽度.高度的简单介绍: scrollHeight: 获取对象的滚动高度. scrollLeft:设置或获取位于对象左边界和窗口中目前可见内容的最左端之间的距离 scrollTop:设置或获 ...

  2. Python自动化运维技术与最佳实现

    第一章 系统基础信息模块详解 系统基础信息采集模块最为监控模块的重要组成部分,能够帮助运维人员了解当前系统的健康程度,同时也是衡量业务的服务质量的依据,比如系统资源吃紧,会直接影响业务的质量以及用户的 ...

  3. ORM详解,ORM Object relation mapping (对象关系映射)

  4. 解决报错(Could not create connection to database server.)

    org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory 尝试多种方法后发现是由于mysq ...

  5. HDU 6582 Path

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submissio ...

  6. python 指定画图分辨率

    from IPython.core.pylabtools import figsize # import figsize figsize(12.5, 4) # 设置 figsize plt.rcPar ...

  7. 730KII 打印机 Win7 2017年11月更新系统补丁后无法打印

    卸载11月份编号为KB4048960的系统更新

  8. 使用JLDAP操作LDAP,包含匿名连接、ldif导入导出、获取根节点、对数据的操作、LDAP错误码解析等

    bean类 package com.cn.ccc.ggg.ldap.model; import javax.persistence.Entity; import javax.persistence.T ...

  9. VS2015中添加QT5.9.0插件

    https://blog.csdn.net/hhhuang1991/article/details/79768595 VS2015里使用QTDIR路径查找QT开发包目录 路径配置操作系统环境变量里添加 ...

  10. 接上SQL SERVER的锁机制(一)——概述(锁的种类与范围)

    二.完整的锁兼容性矩阵(见下图) 对上图的是代码说明:见下图. 三.下表列出了数据库引擎可以锁定的资源. 名称 资源 缩写 编码 呈现锁定时,描述该资源的方式 说明 数据行 RID RID 9 文件编 ...