webpack常用配置

2019-10-15 webpack

# webpack常用配置

# 1.安装核心模块

  • webpack
  • webpack-cli

** 注意: 因为在webpack 3中,webpack本身和它的CLI以前都是在同一个包中,但在第4版中,他们已经将两者分开来更好地管理它们。

为了方便,在package.json增加

"scripts": {
    "webpack01": "webpack"
 }

目录建立关系 image.png

执行npm run webpack01 即可进行打包。 image.png

由于没有配置文件,他会走自己的默认选项,且模式是mode:production ** 解释: 如果执行 npm run webpack01 ,会在找当前文件夹下的寻找webpack.config.js。如果找到会执行这个文件中的配置。如果没有找到也不会报错。会执行本身的0配置。 当然我们很少使用这样的配置文件。因此我们一般会自定义配置文件。 目录路径: webpack/01/webpack.base.js

const path = require('path');
module.exports = {
  mode:'development',
  entry:'./src/index.js',
  output:{
    filename:'bundle.js',
    path:path.resolve('build')
  }

}

# 2.entry

image.png 基本的使用方法是:

module.exports = {
  entry:'./src/index.js',
  // 或者
  entry:['index.js','main.js'],
    // 或者
  entry:{
    "index.js":"index.js",
    "main.js":"main.js"
  }
    // 或者
  entry:{
   "index.js":["index.js","main.js"],
    "main.js":["main.js","index.js"]
	},
    // 或者
  entry:{
   "index.js":["index.js","main.js"],
    "main.js":["main.js","index.js"]
	}, 
   // 或者(这种不常用) 
  entry: () => './demo'  
}

# 3.output

output里面的参数比较多,这里值介绍一个主要的参数;

module.exports = {
  output:{
    filename:'[id].[name].[hash:8].js',// hash,chunkhash,contenthash,
    library: 'MyLibrary',// 定于 打包出来变量的名称
    // 暴露为一个变量(一般不使用这种方式)
    libraryTarget: "var"// var,this,window,global,commonjs,assign,
    //模块定义系统
    libraryTarget: "commonjs2"// commonjs2,amd,umd
    path: path.resolve('build'),
    publicPath: 'https://cdn.example.com/assets/'    
  }
}

注意: image.png 详细的 请看webpack output (opens new window)

# 4.webpack-dev-server

文档链接:中文 (opens new window) 英文 (opens new window)

常用方式

devServer: {
			contentBase: "./build/", //监听代码变化自动提交并刷新网页
			host: '0.0.0.0',
			port: 8080,
			proxy: { //配置代理
				'/web/webApi': {
					target: 'http://t1.zhuhuiyao.cn',
					secure: false,
					changeOrigin: true
				}
			}
}

// 使用node启动

var compiler = webpack(config);
const server = new WebpackDevServer(
  compiler,
  {
    contentBase: path.join(__dirname, '../'),
    quiet: true,
    publicPath: '/dist/',   //publicPath必填 否则就不好使
    hot: true,
    compress: true,
    historyApiFallback: true,
  }
)
server.listen(8080)

# webpack-dev-server提供了两种自动刷新模式:iframe和inline

# iframe

# 特点

  1. 在网页中嵌入了一个iframe,将我们自己的应用注入到这个iframe当中去。

  2. 在页面头部有一个提示框,用于显示构建过程的状态信息。

  3. 加载了live.bundle.js文件,其不但创建了iframe标签,同时包含socket.ioclient代码,以和webpack-dev-server进行websocket通讯,从而完成自动编译打包、页面自动刷新的功能。

  4. Iframe mode下,浏览器访问的路径是:

localhost:8080/webpack-dev-server/index.html。

这个时候这个页面的header部分会出现整个reload消息的状态。当源文件改变的时候,即可以完成自动编译打包、页面自动刷新的功能。

#

# 原理

当使用Iframe mode时,请求/webpack-dev-server/index.html路径时,会返回client/index.html文件,这个文件的内容就是:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
        <meta charset="utf-8"/>
        <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"/>
        <script type="text/javascript" charset="utf-8" src="/__webpack_dev_server__/live.bundle.js"></script>
    </head>
    <body></body>
</html>

可看出,这个页面会请求live.bundle.js文件,该文件里面会新建一个Iframe,你的应用就被注入到了这个Iframe当中。 同时live.bundle.js中含有socket.ioclient代码,这样它就能和webpack-dev-server建立的http server进行websocket通讯了。并根据返回的信息完成相应的动作。

# inline

# 特点

  1. 构建消息在浏览器控制台显示。
  2. socket.ioclient代码被打包进了你的包(bundle)中,以此来与webpack-dev-server进行websocket通讯,从而完成自动编译打包、页面自动刷新的功能。
  3. 但是,每一个入口文件都会被插入上述的一段脚本,使得打包后的bundle文件很臃肿。

使用inline mode的时候,这个时候访问的路径是:

localhost:8080/index.html

Inline mode也能完成自动编译打包、页面自动刷新的功能,但是页面没有header部分reload消息的显示,不过在控制台中会显示reload的状态。

# 原理

Inline-mode,是webpack-dev-server会在你的webpack.config.js的入口配置文件中再添加一个入口,

module.exports = {
        entry: {
            app: [
                'webpack-dev-server/client?http://localhost:8080/',
                './src/js/index.js'
            ]
        },
        output: {
            path: './dist/js',
            filename: 'bundle.js'
        }
    }

这样就完成了将inlined.js打包进bundle.js里的功能,同时inlined.js里面也包含了socket.ioclient代码,可以和webpack-dev-server进行websocket通讯。 当然你也可以直接在你index.html引入这部分代码:

<script src="http://localhost:8080/webpack-dev-server.js"></script>

# 总结

  1. Iframe modeInline mode最后达到的效果都是一样的,都是监听文件的变化,然后再将编译后的文件推送到前端,完成页面的reload的。
  2. 通过设置devServer.inline切换两种模式,默认为inline模式。
  3. 当使用HMR功能时,推荐使用inline mode

# 5.loader

# 5.1 loader的特点

loader的特点,指责单一 使用多个loader需要用数组的形式 loader的执行顺序 默认是从右到左,从下到上。 loader 可以写成对象的形式

# 5.2 css 常用的cssloader

style-loader 把css 加入到 html中 css-loader // @import 解析路径 less-loader // 把less -> css postcss-loader//  添加兼容性 mini-css-extract-plugin // 将css 单独提出到一个文件中 optimize-css-assets-webpack-plugin // 装css进行压缩

# 5.3 babel-loader

常见配置方法。 官网链接 (opens new window)

rules: [
  // the 'transform-runtime' plugin tells babel to require the runtime
  // instead of inlining it.
  {
    test: /\.js$/,
    exclude: /(node_modules|bower_components)/,
    use: {
      loader: 'babel-loader',
      options: {
        presets: ['@babel/preset-env'],
        plugins: ['@babel/transform-runtime']
      }
    }
  }
]

想解决兼容性,及其减少依赖包的体积,请看下面这篇文件。 babel-polyfill VS babel-runtime VS babel-preset-env (opens new window)

# 5.4 eslint-loader

网站链接: eslint 中文 (opens new window) eslint 英文 (opens new window) image.png 可以自定义配置规则。

 rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "eslint-loader",
        options: {
          // eslint options (if necessary)
        }
      }

# 6. html-webpack-plugin

常用用法:

{
  entry: 'index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'index_bundle.js'
  },
  plugins: [
    new HtmlWebpackPlugin(), // Generates default index.html
    new HtmlWebpackPlugin({  // Also generate a test.html
      filename: 'test.html',
      template: 'src/assets/test.html',
      chunks: ['entry']
    })
  ]
}

具体参考github仓库 (opens new window)

# 7. 引入全局模块

# 减少依赖包体积。

1.expose-loader 过于简单,不讲

2.webpack.ProvidePlugin

new webpack.ProvidePlugin({
  Vue: ['vue/dist/vue.esm.js', 'default']
})
externals: {
        jquery: 'jQuery'
}

8.sourceMap image.png

# 8.watch 和 watchOptions 实现实时打包

官网案例 (opens new window)

watch: false,
watchOptions: {
  aggregateTimeout: 300,
  poll: 1000
}

# 9.常用小插件及其优化策略

1.copy-webpack-plugin 2.clean-webpack-plugin 3.webpack-merge 4.webpack.BannerPlugin 5.webpack.DefinePlugin 6.webpack.IgnorePlugin 7.DllPlugin DllReferencePlugin提高构建速度 (opens new window) 8.happypack

const webpack = require('webpack');

new webpack.BannerPlugin(banner);

new webpack.DefinePlugin({
  // Definitions...
});
const HappyPack = require('happypack');

exports.module = {
  rules: [
    {
      test: /.js$/,
      // 1) replace your original list of loaders with "happypack/loader":
      // loaders: [ 'babel-loader?presets[]=es2015' ],
      use: 'happypack/loader',
      include: [ /* ... */ ],
      exclude: [ /* ... */ ]
    }
  ]
};

exports.plugins = [
  // 2) create the plugin:
  new HappyPack({
    // 3) re-add the loaders you replaced above in #1:
    loaders: [ 'babel-loader?presets[]=es2015' ]
  })
];

# webpack 自带优化

image.png

tree-shaking原理 (opens new window)

# noParse

防止 webpack 解析那些任何与给定正则表达式相匹配的文件。忽略的文件中不应该含有 importrequiredefine 的调用,或任何其他导入机制。忽略大型的 library 可以提高构建性能。

 module: {
    noParse: /jquery|lodash/,
  }

# 懒加载

function sayHello() {
  import('./non-esm.js').then(module => {
    module.default.sayHello();
  });
}

# 热更新,热加载

花裤衩 (opens new window)详解

# 10.resolve

resolve: {
    alias: {
      Utilities: path.resolve(__dirname, 'src/utilities/'),
      Templates: path.resolve(__dirname, 'src/templates/')
    },
    extensions: ['.wasm', '.mjs', '.js', '.json']
  }

# 11.optimization

官网 (opens new window)

optimization: {
    minimize: false,
    minimizer: [
      new TerserPlugin({
        cache: true,
        parallel: true,
        sourceMap: true, // Must be set to true if using source-maps in production
        terserOptions: {
          // https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions
        }
      }),
    ],
  splitChunks:{},
  }
最后更新: 2019-10-15 8:10:02 ├F10: PM┤