学习webpack的第二天

145 阅读4分钟

遇到问题1

{
    test: /\.(js|jsx|vue)$/,
    exclude: /src\/util\/log/,
    loader: './build/loader/word-check-loader.js'
}

中./build/loader/word-check-loader.js中导出的是什么?

答案:所谓 loader 只是一个导出为函数的 JavaScript 模块;


遇到问题2

const chalk = require('chalk')
const { stderr, exit } = require('process')
module.exports = function(src) {
  if (src.indexOf('countLog') !== -1) {
    stderr.write(chalk.red(`\n\n【${this.resource}】\n\n`))
    stderr.write(chalk.red(`【代码中直接调用countLog可能会导致线上报错,请使用src/util/log】\n\n`))
    exit(1)
  }
  return src
}

word-check-loader.js文件本身中的function(src)中的src又指代什么?

答案:然后把上一个 loader 产生的结果或者资源文件(resource file)传入进去;

word-check-loader.js文件本身中的${this.resource}中的this又指代什么?

答案:函数的 this 上下文将由 webpack 填充;

官方文档:loader API


遇到问题3

const VueLoaderPlugin = require('vue-loader/lib/plugin');
module: {
    rules: [
      // ... 其它规则
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }
    ]
},
new VueLoaderPlugin(), // vue-loader插件开启

vue-loader配置的方式为什么还需要plugin?且为什么需要vue-template-compiler配合?

答案: 每个 vue 包的新版本发布时,一个相应版本的 vue-template-compiler也会随之发布。编译器(就是指vue-template-compiler)的版本必须和基本的 vue 包保持同步,这样vue-loader就会生成兼容运行时的代码。这意味着你每次升级项目中的 vue 包时,也应该匹配升级 vue-template-compiler。

答案: 这个插件是必须的! 它的职责是将你定义过的其它规则复制并应用到 .vue 文件里相应语言的块。例如,如果你有一条匹配/\.js$/的规则,那么它会应用到 .vue 文件里的 <script> 块。


遇到问题4

配置完vue-loader等之后中,发现vue中等资源文件还是存在问题,那么在vue中怎么处理资源文件的?

html
<img src="../image.png"> 
css
.class {
    background: url('../image.png')
}
js
document

最终转化为
createElement('img', {
  attrs: {
    src: require('../image.png') // 现在这是一个模块的请求了
  }
})

所以也会将所有遇到的资源 URL 转换为 webpack 模块请求,url-loader 和 file-loader,那么url-loader是将资源转化为base64,使用于小资源等文件,file-loader适用于大文件,但是要注意路径解析的问题

扩充知识

  1. 自定义loader的入参和输出?

    第一个 loader 的传入参数只有一个:资源文件(resource file)的内容。compiler 需要得到最后一个 loader 产生的处理结果。这个处理结果应该是 String 或者 Buffer(被转换为一个 string),代表了模块的 JavaScript 源码。另外还可以传递一个可选的 SourceMap 结果(格式为 JSON 对象)。

  2. 同步loader VS 异步loader?

    我们建议尽可能地使你的 loader 异步化。但如果计算量很小,同步 loader 也是可以的。

  3. require('./loader1?xyz!loader2!./resource?rrr');这句中的?!分别是什么

    ?是指:参数,

    !两个loader的连接符,并且和[]前后顺序是相反的,比如loader1!loader2 === [loader2,loader1]

  4. 下面这个方法中的sourceMap是指,映射关系,比如我们经常开启的dev环境中js的sourceMap

    this.callback(
        err: Error | null,
        content: string | Buffer,
        sourceMap?: SourceMap,
        meta?: any
    );
    
  5. 开发中的webpack.dev中的配置项基本有devtool,devServer

    1. devtool主要配置sourceMap
    2. devServer主要配置,比如热更新hot;资源文件根目录contentBase;默认打开open;代理proxy;publicPath(对比output里面的publicPath);打包进度progress(只用于cli工具);lazy请求资源时才打包资源;header在所有响应中添加首部内容;quiet初始启动信息之外的任何内容都不会被打印到控制台。这也意味着来自 webpack 的错误或警告在控制台不可见;noInfo隐藏所有控制台信息;stats就是可以配置的控制台信息;
    3. 一般所有的devServer都可以用cli工具
  6. 要总结一下webpack里面关于path、publicPath和contentBase的区别及用法。

    1. output里面的path表示的是output目录对应的一个绝对路径,webpack打包生成的文件目录。
    2. output里面的publicPath表示的是打包生成的index.html文件里面引用资源的前缀
    3. devServer里面的publicPath表示的是打包生成的静态文件所在的位置,如果静态文件中动态加入js,css文件,这些文件的前缀还是output里面的publicPath(若是devServer里面的publicPath没有设置,则会认为是output里面设置的publicPath的值),所以这两者可以只设置一个,同步静态文件和动态文件访问路径一致
    4. devServer里面的contentBase表示的是告诉服务器从哪里提供内容。(只有想提供静态文件时才需要)

引用文章