个人系列博客链接


title:webpack基础


1 webpack CLI (Command Line Interface)

常用配置

webpack --help (webpack -h)  列出命令行所有可用的配置选项
webpack --config example.config.js
webpack 命令默认执行  webpack.config.js

环境变量. nodeProcess.env

webpack --env.production    # 设置 env.production == true
webpack --env.platform=web  # 设置 env.platform == "web"
webpack --env.NODE_ENV=local --env.production --progress
如果设置 env 变量,却没有赋值,--env.production 默认将 --env.production 设置为 true

其他配置

配置文件多种配置类型-对象,函数

2管理资源

+ |– /components
+ |  |– /my-component
+ |  |  |– index.jsx
+ |  |  |– index.css
+ |  |  |– icon.svg
+ |  |  |– img.png

这种配置方式会使你的代码更具备可移植性,因为现有的统一放置的方式会造成所有资源紧密耦合在一起。假如你想在另一个项目中使用 /my-component,只需将其复制或移动到 /components 目录下。

3 webpack 缓存管理链接

4 代码分离

重点:

1 bundle 分析(bundle analysis) 先学会如何利用这个插件来了解webpack的打包情况;

2 以ele提供模版参考element-starter

参考官网

  • 入口起点:使用 entry 配置手动地分离代码。
  • 防止重复:使用 CommonsChunkPlugin 去重和分离 chunk。
  • 动态导入:通过模块的内联函数调用来分离代码。
npm run dev
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>element-starter</title>
</head>

<body>
  <div id="app"></div>
<script type="text/javascript" src="/assets/index.js"></script>
<script type="text/javascript" src="/assets/vendor.js"></script></body>

</html>
  • 启动项目之后,在控制台查看network分析
  • 入口文件生成的不同的bundle都被动态的添加到index.html中,加载index.html之后,通过script进行加载

性能优化:

  • entry有几个入口起点,就会在index.html中动态插入几个bundle,可以通过拆分bundle,减少bundle的大小
  • 假如a.js. b.js 都引入了 import lodash from 'lodash'

注意:HtmlWebpackPlugin插件会先将 多个入口的公用库 在通过 CommonsChunkPlugin插件提取公共bundle的时候,优先导入index.html文件

4.1 入口起点(没有设置CommonsChunkPlugin插件的时候)

注意:

  • 如果传入一个字符串或字符串数组,chunk 会被命名为 main
entry:'./src/main.js',
<script type="text/javascript" src="vendorddd.js?1e2bb5c4a74e8d3950a2"></script><script type="text/javascript" src="main.js?363487fd4d1508087ee4"></script>
  • 如果传入一个对象,则每个键(key)会是 chunk 的名称,该值描述了 chunk 的入口起点。
entry: {
    index: './src/main.js',
    vendor: './src/vendor'  
},
    //or
entry: {
    vendor: './src/vendor',
    index: './src/main.js',
},

以上根据HtmlWebpackPlugin插件生成的都是如下:

<script type="text/javascript" src="index.js?0404cb6d254c943fe5f4"></script><script type="text/javascript" src="vendor.js?de6b638d85297a1b138b"></script></body>

如果使用 CommonsChunkPlugin插件 ,那么webpack生成的chunk中会有 manifest 和 runtime 这两个chunk

new webpack.optimize.CommonsChunkPlugin({
    names:  ['vendor','manifest','runtime']
}),

4.2 入口起点设置CommonsChunkPlugin插件

接受配置如下:

{
  name: string, // or
  names: string[],
  // 这是 common chunk 的名称。已经存在的 chunk 可以通过传入一个已存在的 chunk 名称而被选择。
  // 如果一个字符串数组被传入,这相当于插件针对每个 chunk 名被多次调用
  // 如果该选项被忽略,同时 `options.async` 或者 `options.children` 被设置,所有的 chunk 都会被使用,
  // 否则 `options.filename` 会用于作为 chunk 名。
  // When using `options.async` to create common chunks from other async chunks you must specify an entry-point
  // chunk name here instead of omitting the `option.name`.

  filename: string,
  // common chunk 的文件名模板。可以包含与 `output.filename` 相同的占位符。
  // 如果被忽略,原本的文件名不会被修改(通常是 `output.filename` 或者 `output.chunkFilename`)。
  // This option is not permitted if you're using `options.async` as well, see below for more details.

  minChunks: number|Infinity|function(module, count) -> boolean,
  // 在传入  公共chunk(commons chunk) 之前所需要包含的最少数量的 chunks 。
  // 数量必须大于等于2,或者少于等于 chunks的数量
  // 传入 `Infinity` 会马上生成 公共chunk,但里面没有模块。
  // 你可以传入一个 `function` ,以添加定制的逻辑(默认是 chunk 的数量)

  chunks: string[],
  // 通过 chunk name 去选择 chunks 的来源。chunk 必须是  公共chunk 的子模块。
  // 如果被忽略,所有的,所有的 入口chunk (entry chunk) 都会被选择。


  children: boolean,
  // 如果设置为 `true`,所有  公共chunk 的子模块都会被选择

  deepChildren: boolean,
  // If `true` all descendants of the commons chunk are selected

  async: boolean|string,
  // 如果设置为 `true`,一个异步的  公共chunk 会作为 `options.name` 的子模块,和 `options.chunks` 的兄弟模块被创建。
  // 它会与 `options.chunks` 并行被加载。
  // Instead of using `option.filename`, it is possible to change the name of the output file by providing
  // the desired string here instead of `true`.

  minSize: number,
  // 在 公共chunk 被创建立之前,所有 公共模块 (common module) 的最少大小。
}
4.2.1 提取多入口公共部分,会额外生成一个 chunk(每个入口都会生成一个chunk)
entry: {
    app: './src/app',
    index: './src/main.js',
},
new webpack.optimize.CommonsChunkPlugin({
    name:'commons'
}),
<script type="text/javascript" src="commons.js?72cc5aafa56e436c4610"></script><script type="text/javascript" src="index.js?db019f512b2790009263"></script><script type="text/javascript" src="app.js?34b940d4b77ffe921124"></script></body>

以上会将app.jsindex.js的公用部分提取出来;

4.2.2 设置公用库
entry: {
    vendor: ['lodash','vue'],
    index: './src/main.js',
},
new webpack.optimize.CommonsChunkPlugin({
    name:'vendor'
}),

可以发现通过 CommonsChunkPlugin 明确第三方库 chunk,并且会优先加载

<script type="text/javascript" src="vendor.js?2f90511bd9c96a3ace4b"></script><script type="text/javascript" src="index.js?db019f512b2790009263"></script></body>
4.2.3 公用库的bundle缓存配置 官方链接
 entry: {
    vendor: ['lodash','vue'],
    index: './src/main.js',
  },
new webpack.NamedModulesPlugin(),    
    new webpack.optimize.CommonsChunkPlugin({
    names:  'vendor'
}),
    new webpack.optimize.CommonsChunkPlugin({
    names:  'manifest'
}),

webpack.config.js

const resolve = require('path').resolve
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const url = require('url')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const publicPath = ''

module.exports = (options = {}) => ({
  // entry:'./src/main.js',
  entry: {
    vendor: ['lodash','vue'],
    
    index: './src/main.js',
    
  },
  output: {
    path: resolve(__dirname, 'dist'),
    //entry 入口文件导出的文件名会以这个为准
    filename: options.dev ? '[name].js' : '[name].js?[chunkhash]',
    //非入口文件导入的文件,比如动态导入的文件,会以这个为准
    chunkFilename: '[name].js?[chunkhash]',
    publicPath: options.dev ? '/assets/' : publicPath
  },
  module: {
    rules: [{
        test: /\.vue$/,
        use: ['vue-loader']
      },
      {
        test: /\.js$/,
        use: ['babel-loader'],
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader', 'postcss-loader']
      },
      {
        test: /\.(png|jpg|jpeg|gif|eot|ttf|woff|woff2|svg|svgz)(\?.+)?$/,
        use: [{
          loader: 'url-loader',
          options: {
            limit: 10000
          }
        }]
      }
    ]
  },
  plugins: [
    new webpack.NamedModulesPlugin(),    
    new webpack.optimize.CommonsChunkPlugin({
      names:  'vendor'
    }),
    new webpack.optimize.CommonsChunkPlugin({
      names:  'manifest'
    }),
    new HtmlWebpackPlugin({
      template: 'src/index.html'
    }),
    new BundleAnalyzerPlugin()
  ],
  resolve: {
    alias: {
      '~': resolve(__dirname, 'src')
    },
    extensions: [".js", ".json",".vue"]

  },
  devServer: {
    host: '127.0.0.1',
    port: 8010,
    proxy: {
      '/api/': {
        target: 'http://127.0.0.1:8080',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    },
    historyApiFallback: {
      index: url.parse(options.dev ? '/assets/' : publicPath).pathname
    }
  },
  devtool: options.dev ? '#eval-source-map' : '#source-map'
})

jimwmg
151 声望4 粉丝

点点滴滴,不忘初心


« 上一篇
Vue源码解析