一文速览Webpack

栏目: JavaScript · 发布时间: 5年前

内容简介:入口,Webpack执行构建的第一步将从entry开始,可抽象成输入;输出结果,在Webpack经过一系列处理并得到最终想要的代码后输出结果;模块转换器,用于将模块的原内容按照需求转换成新内容;

入口,Webpack执行构建的第一步将从entry开始,可抽象成输入;

module.exports = {
  entry: './main.js'
};
复制代码

output

输出结果,在Webpack经过一系列处理并得到最终想要的代码后输出结果;

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, './dist');
  }
};
复制代码

loader

模块转换器,用于将模块的原内容按照需求转换成新内容;

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, './dist');
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader?minimize'],
      }
    ]
  }
};
复制代码

plugins

扩展插件,在Webpack构建流程中的特定时机注入扩展逻辑,来改变构建结果或我们想做的事情;

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, './dist');
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        loaders: ExtractTextPlugin.extract({
          use: ['css-loader']
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin({
      fliename: `[name]_[contenthash:8].css`,
    })
  ]
};
复制代码

module

模块,在Webpack里一切皆模块,一个模块对应一个文件。Webpack会从配置的entry开始递归找出所有依赖的模块;

chunk

代码块,一个chunk由多个模块组合而成,用于代码合并与分割;

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

2. 基本配置

1. Entry

  • context

Webpack在寻找相对路径的文件时会以context为根目录,context默认为当前所在的工作目录, 注意context必须是一个绝对路径的字符串

module.exports = {
  context: path.resolve(__dirname, 'app'),
};
复制代码
  • Entry类型
类型 例子 含义
String './main.js' 入口模块的文件路径,可以是相对路径
Array ['./main.js', './app.js'] 入口模块的文件路径,可以是相对路径
Object {a: './main.js', b: './app.js'} 配置多个入口,每个入口生成一个chunk
  • chunk的名称

chunk的名称和entry的配置有关,如果entry是一个String或Array,只会生成一个chunk;如果entry是一个Object,就会生成多个chunk,名称为Object中的key。

  • 配置动态Entry

如果不确定有多少个页面入口,可以设置为一个函数动态的返回entry配置;

// 同步函数
entry: () => {
  return {
    a: './page1/index',
    b: './page2/index'
  }
}
// 异步函数
entry: () => {
  return new Promise( (resolve) => {
    resolve({
      a: './page1/index',
      b: './page2/index'
    })
  })
}
复制代码

2. Output

  • filename

filename是配置输出的文件名称,为string类型,如果只有一个输出文件可以写死为bundle.js,但是有多个输出时可以借助模板变量 [name].js ,常用的变量包括:

变量名称 含义
id Chunk的唯一标识,默认从0开始
name Chunk的名称
hash Chunk的唯一标识的Hash值,[hash:8]代表取8位Hash值,默认是20位
chunkhash Chunk内容的Hash值,取值同上
  • chunkFilename

用于指定在运行过程中生成的Chunk在输出时的文件名称,常见场景为使用CommonChunkPlugin;支持和filename一致的内置变量;

  • path

配置输出文件的本地目录,为string类型的绝对路径,支持字符串模板,内置变量只有一个Hash;

module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist_[hash]')
  }
};
复制代码
  • publicPath

配置发布到线上资源的URL前缀,为string类型的相对路径,默认为'',也支持字符串模板,内置变量只有一个Hash;

module.exports = {
  output: {
    filename: '[name]_[chunkhash:8].js',
    publicPath: 'https://XX.cdn.com/static/' 
  }
};
复制代码
  • crossOriginLoading

Webpcak输出的部分代码块可能需要异步加载,是通过JSONP方式实现的,所以可以在 <script> 标签中设置crossorigin属性,常用来获取异步加载的脚本执行时的详细错误信息。

crossorigin属性值 含义
anonymous(默认) 在加载此脚本资源时 不会 带上用户的cookie
use-credentials 在加载此脚本资源时 带上用户的cookie
  • LibraryTarget和library

当用Webpack去构建一个可以被其他模块导入使用的库时,需要用到LibraryTarget和library,它们通常搭配在一起使用,推荐使用 Rollup 来构建基础库;

LibraryTarget配置以何种方式导出库,常用的有var/this/commonjs/window/global等;

Library配置导出库的名称,配合LibraryTarget一起使用;
复制代码
  • LibraryExport

配置为要导出的模块中哪些子模块需要被导出,它只有在output.libraryTarget被设置为commonjs或者commonjs2时使用才有意义;

// 某模块源代码
export const a = 1;
export default b = 2;

// 如果在output.libraryExport设置为a;那么将构建输出的代码和使用方法将变成以下内容:
// Webpack输出的代码
module.export = lib_code['a'];
// 使用库的方法
require('library-name') === 1;
复制代码

3. Module

  • 配置Loader

rules配置模块的读取和解析规则,通常用来配置Loader。类型为数组,数组里的每一项都描述了如何处理部分文件,每一项大致有如下三种方式来完成;

  1. 条件匹配 : 通过 test、include、exclude 三个配置项来选中Loader要处理的文件;
  2. 应用规则 : 对选中的文件通过 use 配置项来应用Loader,也可以是一个,也可以是按照从后往前的顺序一组Loader,同时可以分别向Loader传入参数;
  3. 重要顺序 : 一组Loader的默认顺序是从右往左执行的,通过 enforce 选项可以将其中一个Loader放在最前( pre )或最后( post );
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [{
          loader: 'babel-loader',
          options: {
            cacheDirectory: true
          },
          enforce: 'post'
        }],
        include: path.resolve(__dirname, 'src'),
      },
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader'],
        exclude: path.resolve(__dirname, 'node_modules')
      }
    ]
  }
};
复制代码
  • noParse

该可选配置项可以让Webpack忽略对部分没采用模块化的文件的递归解析和处理,从而提高构建性能,类型为RegExp、[RegExp]、Function中的一种, 注意被忽略的文件里不能包含import、require、define等模块化语句 ,不然会导致在浏览器中无法执行该模块化语句;

// 正则形式
noParse: /jquery|chartjs/
// 函数形式
noParse: (content) => {
  return /jquery|chartjs/.test(content);
}
复制代码
  • parser

该配置项可以精确到语法层面,让Webpack只解析对应的模块化文件;

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        use: ['babel-loader'],
        include: path.resolve(__dirname, 'src'),
        parser: {
          amd: false,
          commonjs: true,
          requirejs: false,
          harmony: true
        }
      }
    ]
  }
};
复制代码

4. Resolve

  • alias

该配置项通过别名来将原导入路径映射成一个新的导入路径;

module.exports = {
  resolve: {
    alias: {
      @components: './src/common/components',
      @assets: './src/common/assets'
    }
  }
};
复制代码
  • mainFields

有一些第三方模块会针对不同的环境提供几份代码,例如分别提供ES5和ES6两份代码,Webpack会根据mainFields的配置去决定优先采用哪份代码,如果想优先采用ES6的代码,则可以这样配置:

mainFields: ['jsnext:main', 'browser', 'main'],
复制代码
  • extensions

在导入语句没带文件后缀时,Webpack会自动带上后缀尝试访问文件是否存在,默认是:

extensions: ['.js', '.json'],
复制代码

如果我们想让Webpack优先使用typescript文件,则可以这样配置:

extensions: ['.ts', '.js', '.json']
复制代码
  • modules

配置Webpack去哪些目录下寻找第三方模块,有时候我们项目中的大量模块会放在common下面,则可以这样去配置:

modules: ['./src/common', 'node_modules']
复制代码
  • descriptionFiles

该配置项是描述第三方模块的文件名称,也就是package.json文件,默认如下:

descriptionFiles: ['package.json']
复制代码
  • enforceExtension

如果resolve.enforceExtension为true,则所有导入语句都必须带后缀,如import './main.js';

  • enforceModuleExtension

和resolve.enforceExtension作用类似, 专门针对node_modules下的模块生效 ,因为第三方模块大部分是不带后缀的,如果resolve.enforceExtension设置为true了,需要把resolve.enforceModuleExtension设为false来兼容第三方模块;

5. Plugin

Plugin的配置很简单,plugins接收一个数组,数组中的每一项都是一个Plugin的实例,Plugin的参数通过构造函数传入;

module.exports = {
  plugins: [
    new CommonChunkPlugin({
      name: 'common',
      chunks: ['a', 'b']
    })
  ]
};
复制代码

6. DevServer

  • hot

开启模块热替换功能,在不刷新整个页面的情况下,通过用新模块替换老模块来做到实时预览;

  • inline

用于配置是否将这个代理客户端自动注入将运行在页面中的chunk里,默认自动注入;

-- 如果开启inline,则devserver会在构建变化后的代码时通过代理客户端控制网页刷新;

-- 如果关闭inline,则devserver会通过iframe的方式去运行要开发的网页,在构建完变化后的代码时,会通过刷新iframe来实现实时预览,这时需要去http://localhost:8080/webpack-dev-server/ 实时预览自己的网页;

  • historyApiFallback

用于方便的开发使用了HTML5的History API的单页应用,总是返回同一个html文件,浏览器会从URL里解析出当前页面的状态,从而显示对应的界面;

  • contentBase

用来配置devserver HTTP服务器的文件根目录,在默认情况下为当前的执行目录,通常是项目的根目录,所以在一般情况下不必设置;

  • headers

可以在http响应中注入一些http响应头,使用如下:

module.exports = {
  devServer: {
    headers: {
      'x-cookie': 12345
    }
  }
};
复制代码
  • host

用于配置devServer服务监听的地址,如果想让局域网的其他设备访问自己的本地服务,则可以在启动devserver时带上参数--host 0.0.0.0;

  • port

用于配置devServer服务监听的端口,默认使用8080端口,如果80端口被其他程序占用则依次+1类推;

  • allowedHosts

配置一个白名单列表,只有http请求的host在该列表中才会正常返回;

  • disableHostCheck

配置是否关闭用于DNS重新绑定的http请求的host检查,devserver默认只接受本地的请求,关闭后可以接收来自任意host的请求;

  • https

devsever默认使用http服务,在某些情况下需要使用https服务时,可以开启此配置,此时devsever会自动为我们在本地生成一份https证书,这时需要重启服务,如HTTP2和Service Worker就必须运行在https上;

  • clientLogLevel

配置客户端的日志等级,会影响我们在浏览器控制台里看到的内容,默认为info级别,即输出所以类型(none/error/warning/info)的日志;

  • compress

配置是否启用Gzip压缩,为Boolean类型,默认为false;

  • open

用于在devserver启动且第一次构建完成时,自动用系统默认浏览器打开我们开发的页面,还提供了openPage配置项来打开指定URL的页面;

7. 其它

  • Target

target配置可以让Webpack构建除针对不同运行环境的代码,常见的有:

target值 含义
web 针对浏览器(默认),所有代码都集中在一个文件里
node 针对nodejs,使用require语句加载chunk代码
async-node 针对nodejs,异步加载chunk代码
webworker 针对webworker
electron-mian 针对Electron主线程
electron-render 针对Electron渲染线程
  • Devtool

配置Webpack如何生成Source Map,默认值是false即不生成,若想构建出的代码生成Source Map方便调试,则可以这样配置:

module.exports = {
  devtool: 'source-map'
};
复制代码
  • Watch和WatchOptions

Webpack支持监听文件更新,在文件发生变化时重新编译,监听模式默认是关闭的,如想打开则配置为:

module.exports = {
  watch: true
};
复制代码

在使用devserver时,监听模式默认开启;除此之外,还可以灵活的控制监听模式;

module.exports = {
  watch: true,
  watchOptions: {
    // 不监听的文件或文件夹,支持正则匹配
    ignored: /node_modules/,
    // 监听到变化后会等300ms再去执行,防抖
    // 默认是300ms
    aggregateTimeout: 300,
    // 判断文件是否发生变化通过不停地询问系统指定文件有没有变化
    // 默认每秒询问1000次
    poll: 1000
  }
};
复制代码
  • Externals

用于告诉Webpack要构建的代码中使用了哪些不用被打包的模块,也就是说这些模版是外部环境提供的,Webpack在打包时可以忽略它们;

module.exports = {
  externals: {
    jquery: 'jQuery'
  }
};
复制代码
  • ResloveLoader

用来告诉Webapck如何去寻找Loader,该配置项常用来加载本地的Loader,默认配置如下:

module.exports = {
  resolveLoader: {
    modules: ['node_modules'],
    extensions: ['js', 'json'],
    mainFields: ['loader', 'main']
  }
};
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

运营之光 2.0

运营之光 2.0

黄有璨 / 电子工业出版社 / 2017-4 / 99

在互联网行业内,“运营”这个职能发展到一定阶段后,往往更需要有成熟的知识体系和工作方法来给予行业从业者以指引。 《运营之光:我的互联网运营方法论与自白 2.0》尤其难得之处在于:它既对“什么是运营”这样的概念认知类问题进行了解读,又带有大量实际的工作技巧、工作思维和工作方法,还包含了很多对于运营的思考、宏观分析和建议,可谓内容完整而全面,同时书中加入了作者亲历的大量真实案例,让全书读起来深入......一起来看看 《运营之光 2.0》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具