第7章:生产环境配置

环境变量

经过DefinePlugin配置环境变量javascript

new webpack.DefinePlugin({
    ENV:JSON.stringify('production'),
    ENV_ID:1234,
    CONSTANTS:JSON.stringify({TYPES:['foo','bar']})
})

注意:咱们在一些值外面加上了JSON.stringify,这是由于DefinePlugin在替换环境变量时对于字符串是直接替换,若是不加JSON.stringify,在替换后就会变成变量名,而非字符串。所以对于字符串环境变量及包含字符串的对象都要加上JSON.stringify才行
设置mode能够默认定义process.env.NODE\_ENVDE的值css

source map

原理

webpack对于工程源码的每一步处理均可能会改变代码的位置,结构甚至是所处文件。因此咱们生成map文件,方便咱们在调试时寻找代码源头。他是源码的映射,能够将压缩后的代码再对应回未压缩的源码。使得咱们在调试线上产品时,就好像在调试开发环境的代码。文件默认就是打包后的文件名加上.map,如bundle.js.map。
在生成map文件的同时,bundle文件中会追加一行注释来标注map文件的位置。如:html

//bundle.js
(function(){
//bundle的内容
})();
//# sourceMappingURL=bundle.js.map

设置sourcemap

module.exports = {
//...
devtool:'source-map'
}

对于css,scss,less来讲须要添加额外的source map配置项java

loaders: {
    css: {
      options:{
        sourceMap: true
      }
    },
    less:{
      options:{
        javascriptEnabled: true,
        sourceMap: true
      }
    }
  }

资源压缩

压缩js

webpack4中默认使用terser的插件terser-webpack-plugin压缩jsjquery

开启压缩

1手动配置webpack

module.exports = {
//...
optimization:{
    minimize:true
}
}

2 生产环境默认配置
设置mode为production后webpack也会默认开启压缩web

压缩css

压缩css的前提时使用mini-css-extract-plugin将样式提取出来。而后手动配置以下代码缓存

//...
{ loader: 'css-loader', options: { sourceMap: true } }

资源缓存

hash、chunkhash、contenthash服务器

hash通常是结合CDN缓存来使用,经过webpack构建以后,生成对应文件名自动带上对应的MD5值。若是文件内容改变的话,那么对应文件哈希值也会改变,对应的HTML引用的URL地址也会改变,触发CDN服务器从源服务器上拉取对应数据,进而更新本地缓存。可是在实际使用的时候,这几种hash计算仍是有必定区别。
咱们先建一个测试案例来模拟下:app

项目结构

咱们的项目结构很简单,入口文件index.js,引用了index.css。而后新建了jquery.js和test.js做为公共库。

//index.js

 require('./index.css')
 module.exports = function(){
  console.log(`I'm jack`)
  var a = 12
 }
//index.css

 .selected : {
   display: flex;
   transition: all .6s;
   user-select: none;
   background: linear-gradient(to bottom, white, black);
 }

接着咱们修改webpack.config.js来模拟不一样hash计算

hash

hash是跟整个项目的构建相关,只要项目里有文件更改,整个项目构建的hash值都会更改,而且所有文件都共用相同的hash值

var extractTextPlugin = require('extract-text-webpack-plugin'),
  path = require('path')
 
 module.exports = {
  context : path.join(__dirname,'src'),
  entry:{
  main: './index.js',
  vender:['./jquery.js','./test.js']
  },
  module:{
  rules:[{
   test:/\.css$/,
   use: extractTextPlugin.extract({
   fallback:'style-loader',
   use:'css-loader'
   })
  }]
  },
  output:{
  path:path.join(__dirname, '/dist/js'),
  filename: 'bundle.[name].[hash].js',
  },
  plugins:[
  new extractTextPlugin('../css/bundle.[name].[hash].css')
  ]
 }

根据上面的配置,咱们执行webpack命令以后,能够获得下面的结果

采用hash计算的执行结果1:

执行结果2:

咱们能够看到构建生成的文件hash值都是同样的,因此hash计算是跟整个项目的构建相关,同一次构建过程当中生成的哈希都是同样的

**chunkhash
**

采用hash计算的话,每一次构建后生成的哈希值都不同,即便文件内容压根没有改变。这样子是没办法实现缓存效果,咱们须要换另外一种哈希值计算方式,即chunkhash。

chunkhash和hash不同,它根据不一样的入口文件(Entry)进行依赖文件解析、构建对应的chunk,生成对应的哈希值。咱们在生产环境里把一些公共库和程序入口文件区分开,单独打包构建,接着咱们采用chunkhash的方式生成哈希值,那么只要咱们不改动公共库的代码,就能够保证其哈希值不会受影响。

var extractTextPlugin = require('extract-text-webpack-plugin'),
  path = require('path')
 
 module.exports = {
  ...
  ...
  output:{
  path:path.join(__dirname, '/dist/js'),
  filename: 'bundle.[name].[chunkhash].js',
  },
  plugins:[
  new extractTextPlugin('../css/bundle.[name].[chunkhash].css')
  ]
 }

采用chunkhash计算的执行结果1:

执行结果2:

咱们能够看到,因为采用chunkhash,因此项目主入口文件Index.js及其对应的依赖文件Index.css因为被打包在同一个模块,因此共用相同的chunkhash,可是公共库因为是不一样的模块,因此有单独的chunkhash。这样子就保证了在线上构建的时候只要文件内容没有更改就不会重复构建

contenthash

在chunkhash的例子,咱们能够看到因为index.css被index.js引用了,因此共用相同的chunkhash值。可是这样子有个问题,若是index.js更改了代码,css文件就算内容没有任何改变,因为是该模块发生了改变,致使css文件会重复构建。
这个时候,咱们能够使用extra-text-webpack-plugin里的contenthash值,保证即便css文件所处的模块里就算其余文件内容改变,只要css文件内容不变,那么不会重复构建。

var extractTextPlugin = require('extract-text-webpack-plugin'),
  path = require('path')
 
 module.exports = {
  ...
  ...
  output:{
  path:path.join(__dirname, '/dist/js'),
  filename: 'bundle.[name].[chunkhash].js',
  },
  plugins:[
  new extractTextPlugin('../css/bundle.[name].[contenthash].css')
  ]
 }

采用contenthash计算的执行结果1:

执行结果2:

html-webpack-plugin

//webpack.config.js 
const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: {
    home: path.resolve(__dirname, './src/app.js')
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
  },
  plugins: [
    new htmlWebpackPlugin({
        template: './src/index.html'//能够指定html模板,方便咱们放入个性化内容。它就会以该html生成一个一摸同样的html文件,而后自动塞入打包后的资源。固然也能够不指定模板。
    })
  ]
}
相关文章
相关标签/搜索