webpack notes

webpack 4 慕课网全套课程学习笔记

1、安装webpack-cli会自动帮我们安装webpack

2、npx webpack index.js 让webpack帮我们翻译index.js(会帮我们翻译和链接ES6的模块,翻译成浏览器能认识的代码)

3、webpack初步认识:JS代码的翻译器。webpack只认识import这样语句,其他高级JS语法它一概不认识。所以称作JS代码的翻译器是高看了它。实际上,webpack的核心定义是模块打包工具。把不同的模块打包到一起。

4、webpack对符合ES Module规范模块、CommonJS规范模块、CMD、AMD模块都能正确认识。

5、webpack发展:纯JS模块打包工具—》css,scss, png, jpg等模块打包

6、npm init完成后配置package.json:

增加“private“:true 属性,说明该项目是私有项目,npm就不会放到共有云上去

去掉”main”: index.js字段,因为我们的项目不会被别人引用,只是自己来用,没有必要向外暴露一个JS文件

7、有时候安装webpack不成功,是因为npm源被国内墙掉了,解决问题方法:用手机分享WiFi热点,再去安装就没问题了。不推荐全局安装webpack(npm install webpack webpack-cli -g),会无法同时使用两个版本的webpack。推荐局部安装(npm install webpack -D // -D 等同于 —save-dev),局部安装无法直接执行webpack命令(如webpack -v), 我们可以执行npx webpack -v, npx会帮我们在当前目录的下node_moudles的包。需要webpack-cli才能支持在命令行执行webpack命令。

8、npm info webpack或其他包:可以看到某个包有哪些版本,npm install [email protected]安装指定webpack版本。

9、webpack默认配置文件:webpack.config.js。 配置中output.path:定义打包出来的文件存放在哪里,必须是绝对路径,如 path.resolve(__dirname, ‘bundle’)。

output.path定义的绝对路径,是整个工程所有打包输出文件的存放根目录。

不同资源的loader配置的options.outputPath定义的相对路径,是相对根目录output.path的存放路径。

10、webpack打包命令行结果提示中的chunks 指的是chunk的ID值,后面的chunk name指的是名称,默认main。因为entry:’./src/index.js‘ 实际上是 entry: { main: ‘./src/index.js’ } 的简写。

webpack的默认模式mode是production,打包出的文件会被压缩。mode的另一个值是development,打包出的文件不会被压缩。

11、webpack官方推荐的loaders和plugins都有很多,配置也有很多。加上个人和机构开发的,有几万个,想全都学会,基本不可能,所以需要套路,学会核心的东西,在实践当中,去查看文档。当然这个方法还不是很好,更好的方法是群里发出来讨论,不用查,直接抛出来,因为每个人处理的业务场景不同,这样大大提高开发效率。

12、webpack只认识JS文件的打包,其他类型的文件需要在module: { rules: [{},{}…] }配置里面告诉webpack怎么处理。

13、webpack遇到图片文件,会求助file-loader, 这个loader会把图片挪到指定的dist目录,然后改个名称(名称可以配置),再返回新的名称给webpack。根据这个原理,file-loader可以打包任何的静态文件,如svg, excel,txt文件,因为静态文件的打包处理大都是直接复制到打包输出目录。

14、var img = new Image() // 这句代码创建了一个image标签

img.src = require(‘./avatar.png’) // 图片经过file-loader处理,返回图片在dist目录的hash名称

img.classList.add(‘avatar’) // 添加样式class

document.getElementById(‘root’).append(img) // 图片插入页面

15、静态资源打包之file-loader参数配置:

use: {
  loader: ‘url-loader’,
  options: {
    name: ‘[name]_[hash].[ext]’, // 使用老静态资源的名字和后缀名。[xxx]称之为placeholder,占位符.
    outputPath: ‘images/’ // 存放于dist目录(webpack配置中output.path配置整个工程dist目录)
  }
}复制代码

16、url-loader: 和file-loader非常类似,只不过多了一个limit的配置项。url-loader完全实现了file-loader能做的,不同之处会根据limit阈值把图片转为base64字符串,打包bundle.js里面。

好处是省了一次HTTP请求,问题是图片很大时,bundle.js很大,页面加载很久才能出来。

url-loader参数配置(和file-loader完全一样,只是多了个limit配置项):

options: {
    name: ‘[name]_[hash].[ext]’,
    outputPath: ‘images/’
    limit: 2048 // 单位字节,小于2kb的才打包进入bundle.js
  }复制代码

17、静态资源打包之(css样式篇)

use: {

loader: [‘style-loader’, ‘css-loader’] // 因为需要2个loader,就不能写成对象值形式,要用数组形式。

}

head里面的style标签,是style-loader帮我们挂载上去的,所以在css-loader处理css文件时需要配合style-loader使用。

18、使用先进css语法之sass-loader: 需安装sass-loader node-sass

use: {

loader: [‘style-loader’, ‘css-loader’, ’sass-loader’] // loader是从右到左的执行顺序

}

19、产商前缀自动添加之postcss-loader: 给CSS3新属性自动添加 moz- webkit- 等厂商前缀

需新建postcss.config.js配置文件:

plugins: [require(‘autoprefixer’)] // 配置需要使用的插件,当postcss-loader被使用的时候,会去使用一

// 个叫autoprefixer的插件,帮我们去加上厂商前缀

webpack配置:

use: {
    loader: [‘style-loader’, {
       loader: ’css-loader’, // 如果需要多个loader,还要给loader传参数,就不能写字符串了,要写对象
       options: {
          importLoaders: 2, // 通过import方式引入的资源也要去走2个loader,sass-loaderpostcss-loader
          modules: true // css module,模块化css让JS模块引入css只在当前模块有效,对其他引入模块无效
    }
     }, ’sass-loader’,’postcss-loader’] 
}
复制代码

20、字体文件(www.iconfont.cn 下载iconfont.css)静态资源,需要file-loader打包拷贝至目标目录。下载字体并拷贝样式至项目详细,参考lesson 3-4。

webpack官方文档介绍:DOCUMENTSTION目录下的Asset Management子目录,介绍了所有的资源文件打包,以及数据文件(如.csv格式的Excel表格)打包的解决方案。

21、使用plugins让打包更便捷:

1、安装html-webpack-plugin,然后require引入,再webpack配置:

(这个插件会在打包结束后自动生成一个HTML文件,并把打包生成的JS自动引入到这个HTML文件中。)

2、安装clean-webpack-plugin, 然后require引入,再webpack配置:

(这个插件会在打包前自动清除指定目录)

plugins: [
        new HtmlWebpackPlugin({ template: ‘src/index.html’ }), // 支持非常多的配置参数,详细看官网
    new CleanWebpackPlugin([‘dist’]) // 也可以用linux命令放至脚本中实现
    ]复制代码

22、Entry和Output基本配置

entry写字符串,等于写键值对(默认的键名是main),如果output.filename指定,覆盖main作为文件名。

output:output.publicPath: ‘cdn.com.cn’ // 所有页面引入的JS都会加上这个地址。当我们的项目,后台服务器用index.html,而静态资源放到CDN的情况下,就会用到output.publicPath配置项。

23、SourceMap配置: sourceMap是一个映射关系,它知道dist目录下main.js文件中的96行实际上对应的是src目录下index.js文件中的第一行。方便我们去源代码排错,而不是去目标代码(打包出来的)排错。

mode: ‘development’, // development模式下自动配置了sourceMap

devtool: ‘none’ 或 ‘eval’ 或 …… // none表示关闭sourceMap.

eval: 以eval方式执行代码,map映射放在js里。虽包速度最快,不生成.map文件,但不适于复杂代码。

cheap-source-map : cheap的意思是只标记出错行,不标记列。只管业务代码的出错,不管第三方插件或loader的出错。

cheap-module-source-map: module的意思是既管业务代码的出错,还管第三方模块,loader出错等。

inline-source-map: inline的意思是把.map文件合并到打包生成的目标js里,以base64编码放在末尾。

最佳实践:

开发环境:cheap-module-eval-source-map。提示较全,打包较快。

线上环境:cheap-module-source-map。

24、使用WebpackDevServer提升开发效率:源码改变,实现自动重新打包。

方式一:命令webpack —watch // watch参数会监听文件改变,自动打包,但需手动刷新浏览器

方式二:安装webpack-dev-server,配置参数:

devServer: { // webpackDevServer会帮助我们启动HTTP一个服务器
      contentBase: ‘./dist’, // 服务器的根目录,就是当前的打包输出目录
      open: true // 自动打开浏览器,并访问localhost:8080
      port: 8080,
      overlay: true,
      proxy: {
        ‘/api’: ‘http://localhost:3000' // 访问localhsot:8080/api 地址会直接转发到 localhost:3000
      }
    }复制代码

命令:webpack-dev-server // 会监听文件改变,自动打包,同时自动刷新浏览器

vue 和 react的底层都使用了webpack-dev-server,所以在vue-cli和react-cli的官方脚手架都同样配置了。

方式三:自己写服务器监听文件改变,自动打包。

1、安装webpack-dev-middleware(做监听) express(做HTTP服务器)
2、const express = require(‘express’)   webpackDevMiddleware= …  webpack= … config= …
3、const compiler = webpack(config)  // 返回一个编译器,编译器执行一次,重新打包一次代码
4、const app = express()  app.use(webpackDevMiddleware(compiler, { 
     publicPath: config.output.publicPath
   }))
  app.listen(8080, () => { console.log(‘server is running’) })
复制代码

25、webpack Hot Module Replacement 热模块更新

div:nth-of-type(odd) { background-color: blue; } // 偶数的子元素背景为蓝色 

 webpac-dev-server帮我们实现自动打包和自动刷新浏览器,但如果我们只改变了某个模块的代码,也会浏览器重新请求页面导致整个页面刷新,这样之前做的交互就会丢失,交互又得重做一遍。 配置参数:

 plugins: [new webpack.HotModuleReplacementPlugin()] // 通过HMR插件实现HMR

 改动的模块重新请求下来后,不会自动执行,需要在引入模块的代码中加入下代码,把更新的模块重新执行一遍。css模块不用自己写这样的代码,是因为css-loader内置了这样的代码。原则上所有想实现热模块更新类型的文件都需要写这样的代码,不需要写的是已经内置了。 

if(module.hot) {   
  module.hot.accpet('./number.js', () =>  
    number();  
  }) 
} 复制代码

当你在代码中去引入其他模块的时候,如果希望某个模块代码发生变化,只希望更新这个模块,就要用到HMR技术。

26、使用babel处理ES6语法(参考Babel官网)

低版本IE浏览器和国产浏览器没有像Chrome与时俱进,更新慢。

ES6转ES5:可以 let 转 var () => {} 转普通函数 function() {}

不可以转:Promise变量和map语法等 需要借助babel-polyfill,在所有代码运行前补充到低版本浏览器里

import “@babel/polyfill” // 在main.js文件头引入模块,这样代码会内联展开并早于业务代码执行

需要安装: babel-loader @babel/core babel核心库,识别JS代码,把JS代码转换为AST抽象语法树,再将AST树编译转化为新的语法。 babel-preset-env包含了所有ES6转ES5的规则。

rules:[{
    test: /.js$/,
    exclude: /node_modules/, // node_modules目录里面是第三方代码,第三方模块自己做过ES6转ES5了
    loader: ”babel-loader”,
    options: {
      presets: [“@babel/preset-env”] // 不传参写法,下面传参写法
      presets: [[“@babel/preset-env”, { useBuiltIns: ‘usage’ , 
        targets: {
          chrome: ‘67’, // 项目会打包运行在大于67版本的浏览器下,让babel根据情况是否转换和填充
          firefox: ’60’, edge:’17’, safari: ’11.1’….
        }
      }]] 
    }
  }]复制代码

useBuiltIns:usage 当用babel-polyfill做填充的时候,根据业务代码用到什么才加什么。减少打包体积。

(webpack4中配置了useBuitin:’usage’的话,webpack会自帮我们引入babel-polyfill,无需手动引。)

通过以上配置,在我们代码中写任何ES6的代码都不会有任何问题了。但是在开发类库、第三方模块、组件库的时候,用babel-polyfille的方案有问题,因为在注入Promise、map等方法时会全局注入,污染全局环境,这时需要换一种配置方式,插件的方式。

(1)安装@babel/plugin-transform-runtime和@babel-runtime,不引入babel-polyfill避免污染全局环境,

(2)更改babel-loader的options配置:(建议是babel配置项非常多,单独建.babelrc配置文件更合适)

options: {
  “plugins”: [[“@babel/plugin-transform-runtime”, {
      “corejs”: 2, // 默认false,改成2需要额外安装@babel/runtime-corejs2代替@babel-runtime
       “helpers”: true, 
       “regenerator”: true,
       “useESModules”: false
    }]]
}复制代码

27、配置React代码的打包 (待看)

28、Tree Shaking

当index.js引入a.js(a.js中有多个方法)中的某一个方法,webpack默认会把a.js中所有方法打包进来。增加了chunk体积。webpack2.0以后提供了摇树功能,但Tree Shaking只支持ES Module(import方式引入的ES Module底层是静态引入,require 引入的Common JS模块是动态引入。)

摇树配置:development模式需要手动配,配好了代码体积也不变少 production模式下默认配好了

(1) webpack.ptimization: {
      usedExports: true,
    }
(2) package.json中配置:”sideEffects”: false, // 避免 import “babel-polyfill”形式引入全部代码被忽略
  或指定具体免忽略清单: “sideEffects”: [‘@babel/poly-fill’, ‘*.css’] // *.css避免忽略任何css复制代码

29、development和production模式的区分打包:production模式下不需要DevServer和new webpack.HotModuleReplacementPlugin(),代码会压缩,sourceMap配置不一样。

配置抽取:webpack.common.js webpack.dev.js webpack.prd.js 通过安装webpack-merge插件合并。

30、Webpack和Code Spliting

plugins: [
    new CleanWebpackPlugin([‘dist’], {
      root: path.resolve(__dirname, ‘../‘) // 指定根目录,该插件默认把当前目录作为根目录
    })
  ]复制代码

安装lodash 工具集合包 import _ from ‘lodash’

默认Webpack 会把工具包和业务代码打包到一个文件,打包文件会很大,加载时间会长,且业务代码一变更打包结果跟着变更,实际上lodash第三方工具包并没有变更。

解决办法(Code Spliting):

第一种:自己分割 (代码分割和webpack无关,在webpack前我们手动分割代码到不同JS文件,然后根据依赖关系顺序引入JS文件)

将第三方工具包拆出来,新建common.js文件,在common.js文件引入各个第三方工具包,并挂在到window全局对象上,然后在页面的entry入口新增一个:

entry: {
  common: ’./src/common.js’,
  main: ‘./src/index.js’
}复制代码

这样打包出来后,index.html会先后引入common.js和main.js,执行结果和将第三方工具包和业务代码打包到一个文件一样。

第二种:webpack中实现代码分割,两种方式

(1)同步代码:只需在webpack中做optimization的配置,借助Webpack插件SplitChunkPlugin实现

optimization: {
     splitChunks: { 
        chunks: ‘all’ // 同步代码需要这样配置才会代码分割,异步代码webpack会自动代码分割到单独文件
      }
  }复制代码

遇到如下代码,webpack会去分析代码,把该提取出来的文件提取出来单独存放:
import xxx from ‘xxx’

// 接着是写业务代码

(2)异步代码:具体通过JSONP异步加载文件,只要是异步加载,webpack会自动做代码分割单独存放到一个文件里去。如下

function getComponent() {
   return import(/* webpackChunkName: “wqloadsh”*/‘lodash’).then(( default: _ )) => {
      return _.join([‘a’,’b’,’c’])
    } // /* webpackChunkName: “wqloadsh”*/ 魔法注释,异步模块打包出来命名成verndors~wqloadsh.js
  } // 若不做上述注释,则loadsh异步模块会被打包出来命名成0.js。复制代码

@babel/plugin-syntax-dynamic-import babel官方提供的这个插件支持魔法注释

31、SplitChunksPlugin配置参数详解

optimazation配置全部是设置同步代码分割和分组规则的。因为异步代码分割就是单独打包到一个文件。

optimazation: {
     chunks: ‘async’, // 默认async表示只对异步代码做代码分割。all表示对同步、异步都做代码分割。
     minSize: 3000, // 引入的同步模块大于3kb才做代码分割
     maxSize: 5000, // 当vendor.js大于5Kb的时候做二次分割,基本不使用这个。 
     minChunks: 2, // 当一个同步模块被多少个打包出来的chunk引用的时候才做代码分割                                                 
     maxAsyncRequests: 5, // 同时加载的模块数最多是5个。    
     maxInitialRequests: 3, // 入口文件main.js做代码分割不超过3个。
     automaticNameDelimiter: ‘~’, // 组和文件之间的连接符号
     cacheGroups: { // 缓存组(即代码分割分组)规则。
       vendors:{ // vendors组
         test: /[/]node_modules[/]/ ,  // 代码分割时,在node_modules目录下的命名为vendors组
         priority: -10 // 对同步异步代码都生效,因此上面异步模块打成单独文件时命名verndors~wqloadsh.js
         filename: ‘vendors.js’ // 一旦发现同步引入的代码从node_modules目录的,都打包到vendors.js
        } ,
    default: { // default组,所有的模块都符合default组,都可以放到default组里。
            priority: -20, // 但是default组的priority会设置的比vendors组低,所有模块优先匹配vendors组。
       reuseExistingChunk: true, // 如果模块以及打包过,直接复用不重复打包。
       filename: ‘common.js’ // 非node_module目录下的同步代码分割到common.js组。
    }
     }
  }复制代码

32、Lazy Loading懒加载,Chunk是什么?

懒加载:通过import()异步加载函数来异步的去加载一个模块,初始不加载,执行import()函数时加载。懒加载不是webpack的概念,而是ES import()函数里面的概念,import().then() 说明import()函数返回的是Promise,如果浏览器不支持Promise则需要安装babel-polyfill。使用:

document.addEventListener(‘click’, () => {
  import(/* webpackChunkName: ‘wqlodash’ */ ‘lodash’).then( { default: _ } => {  _.join([‘aa’, ‘bb’]) })
}) // 异步模块vendors~wqloadsh.js初始不会加载,当点击页面任何位置时才回去加载
// Webpack的异步加载是基于Ajax的JSONP实现的,相比手动创建script标签后插入页面加载JS效果相同。复制代码

ES7 中async关键字写法:

async function getComponent() {
  const { default: _ } = await import(/* webpackChunkName: ‘wqlodash’*/ ’loadsh’)
  _.join([‘aa’, ‘bb’])
}复制代码

chunk是什么:所有JS打包出来的(JS、css)文件都是一个chunk。

optimazation.minChunks: 2, // 当一个同步模块被2个打包出来的chunk引用的时候才做代码分割

33、打包分析,Preloading, Prefetching

官方打包分析:

(1) webpack — profile — json > stats.json 把整个打包过程的描述输出到stats.json文件

(2) webpack.github.io.analyse网站:把stats.json文件上传网站实现可视化分析

assets: 打包出来的静态资源

官方推荐可视化打包工具: webpack-bundle-analyzer

Preloading,Prefetching:

为什么optimization.chunks: ‘async’ 的默认值是async,不对同步代码做分割。这是因为同步代码分割只是把一次引入的main.js代码分割成vendors.js common.js main.js多个文件同时引入,利用缓存避免重复加载vendors.js,common.js这些公共重复代码,达到提高了第二次加载页面的访问速度效果。然而缓存带来的性能提升是非常有限的,真正对页面性能做优化,是需要第一次加载页面时加载速度就是最快的,靠同步代码分割(分割出vendors.js, common.js分组)是满足不了需求的。webpack真正希望我们编写代码的方式是怎样的:

首先观察页面性能:cmd + shift + p,搜索打开Coverage面板,点击开始录制屏幕。然后刷新页面,看到

加载的main.js文件利用率只有74%(红色标注表示未执行代码,绿色标注表示已执行代码)。

性能优化:写高性能代码的时候,现在重点考虑的不是缓存这样的东西,而是代码的使用率。把页面初始不

需要加载的代码变成异步代码,首屏时间就会更短,网页访问速度就会更快。webpack希望我们多去

写异步加载代码,才能让网站加载性能真正得到提升,这也是为什么optimization.chunks: ‘async’ 的

默认值是async,而不是all。

实际应用案例:比如登录弹框,在点击登录按钮后才弹出来,就可以把弹框代码放到点击按钮当中去

import()异步加载。也许会有疑问,如果点击按钮时才去加载异步代码,交互不就会很慢吗,那么

preloading、prefetch就是用来解决这个问题的。

preloading、prefetch:在网络带宽空闲的时候,偷偷的去下载异步代码。等真正执行import()去异步加载

时,其实已经下载到浏览器缓存,这时候就是利用浏览器缓存加载。

案例代码:

document.addEventListener(‘click’, () => {
     import(/* webpackPrefetch: true */ ’./click.js’).then(({ default: func }) => {
       func() // /* webpackPrefetch: true */ 魔法注释,webpack能识别,实现异步代码prefetch
     })
  }) // 把首屏不会执行的交互代码放到了click.js文件,在使用时再异步加载。复制代码

prefetch、preload区别:prefetch等主流程加载完,有空闲再加载,更合适。 preload和主业务文件一起

加载。prefetch在某些浏览器上会有兼容问题。

总结:异步代码+preload/prefetch 是最佳方案。既能实现首屏性能最优,又能实现交互性能最优。

34、CSS文件的代码分割

webpack打包默认css直接打包到JS里(css in js):

output: {
    filename: ’[name].js’, // entry中入口文件JS打包名称走filename配置项,直接被页面引入
    chunkFilename: ‘[name].chunk.js’, // 间接引用(main.js引入)的JS文件打包名称走chunkFilename配置
  }复制代码

使用插件mini-css-extract-plugin(底层依赖SplitChunkPlugin)可以抽取CSS到单独文件,使用:

(1)loaders配置:

test: /.css$/, use: [
       { loader: MiniCssExtractPlugin.loader, options: { publicPath: ‘../‘}},  //最后一步不能再用css-loader
       ‘css-loader’
    ]复制代码

(2)plugins配置:

plugins: [
    new MiniCssExtractPlugin({
    filename: ‘[name].css’, // 被页面直接引用的css名称走这个配置,这个插件默认合并同步css模块。
        chunkFilename: ‘[name].chunk.css // 间接引用(main.css引入)的css名称走这个配置
    }),
    new OptimizeCssAssetsWebpackPlugin({}) // 压缩css的插件
  ]

optimization.splitChunks: {
  cacheGroups: {
    style: {
        name: ‘styles’,
        test: ‘/.css$/‘,
    chunks: ‘all’, // 将所有的css模块,包括同步代码、异步代码,都打包到styles.css一个文件。
    enforce: true // 忽略minSize、minChunks等所有配置参数
    },
    fooStyles: { // MiniCssExtractPlugin官方代码:介绍拆分不同入口JS中引用的CSS代码到不同CSS文件
      name: ‘foo’,
      test: (m,c,entry = ‘foo’) => … // entry中foo.js入口文件中引用的CSS单独打包到foo.css
    },
    barStyles: {
      name: ‘bar’,
      test: (m,c,entry = ‘bar’) => … // entry中bar.js入口文件中引用的CSS单独打包到bar.css
    },
  }
}复制代码

注意:如果在optimization.splitChunks配置了usedExports: true实现treeShaking,则必须在package.json中添加”sideEffects”: [“*.css”]使CSS不被摇树。因为import “xx.css”只引入未显示使用会被摇掉。

35、webpack与浏览器缓存(Cacheing)

performance:false // 关闭webpack性能警告提示

解决浏览器缓存问题: 浏览器非强制刷新不会重新拉取新打包出的同名资源,使用contenthash解决。

output: {
  filename: ‘[name].[contenthash].js’,
  chunkFilename: [name].[contenthash].js
}
老版本的webpack4存在问题,代码不变时,打包出来的contenthash会变,解决:
  optiomization: {
    runtimeChunk: { name: ‘runtime’ } // 把manifest关系代码提取到runtime.js
  }复制代码

原因:业务逻辑代码(main.js)和第三方库(vendors.js)是有关联的,webpack把这关联部分称之为manifest。manifest代码既存在于main.js,也存在于vendors.js,这样即使未改变代码,manifest每次打包都会有差异,同时main.js和vendors.js中的内容也跟着变了,contenthash也就变了。在旧版webpack4中需要我们手动配置抽取manifest代码,新版webpack4已默认帮我们处理。

36、Shimming(加垫片:形式包括babel-polyfill, ProvidePlugin, imports-loader, Authoring Lib等)

webpack打包是基于模块的,模块与模块之间的变量是隔开的。比如a.js引入了jQuery,那么b.js中要想使用$符号,必须自己引入jQuery。

Shimming可以理解为AOP(如过滤器),全局的更改webpack对模块的默认打包行为。

(1) ProvidePlugin:

plugins: [
     new webpack.ProvidePlugin({ // 此插件可自动帮所有模块引入使用了的库
     $: ‘jquery’, // 当webpack发现模块里面用了$符号,webpack会在模块里面自动引入jquery
     _: ‘lodash // 帮使用了_符号的模块自动引入lodash
    _join: [‘lodash’, ‘join’], // 只引入lodash模块中的join方法
     })
  ]复制代码

(2) imports-loader: 每个模块的this默认指向模块自身,imports-loader可以改变所有模块的this,如全部指向window:

{ 
      test: /.js$/, 
      use: [ { loader: ‘babel-loader’ }, 
                { loader: ‘imports-loader?this=>window’ }  // 更改webpack默认行为
       ]  
    }复制代码

37、环境变量的使用

webpack —env.production —config ./build/webpack.common.js //向配置文件传了env.production=true

webpack.common.js:
module.exports = (env) => {
  if(env && env.production) return merge(commonConfig, prodConfig)
  else return merge(commonConfig, devConfig)
}复制代码

38、Library库的打包--打包一个库

1、math.js库 
  export function add() ... mup
2、string.js库
  export function join() ... split
3、index.js
  import * as math from ‘math.js'
  import * as str from 'string.js'
  export default { math, string }
这样index.js暴露出了工具给别人使用,但是这样直接在浏览器上不能运行,需要先进行webpack打包。
webpack配置:
module.exports = {
  mode: 'production',
  entry: './src/index.js',
  externals: ["lodash"], // 声明依赖的外部库,不打包到库里面,而是让业务代码去加载lodash,避免重复打包
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'library.js',
    libraryTarget: 'umd', // 支持任何模块形式的引入,如import,const xx =require,require               (['library'], function() {}) , 
    library: 'library', // 支持
                    
                    

你可能感兴趣的:(webpack)