webpack配置解析

 webpack.config.js 文件解析

const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ClearWebpackPlugin = require('clear-webpack-plugin')

module.exports = {
  mode: 'development',   // 打包模式   测试环境/生产环境
  devtool: 'cheap-module-eval-source-map',   // 是否打包SourceMap文件, 映射代码错误位置
  // 打包入口配置
  entry: {  
    main: './src/index.js',  
  },
  // 使用webpack-dev-server 插件,实现监听代码改动自动打包
  devServer: {
    contentBase: './dist',  // 监听变化的文件
    open: true, // 是否自动打开浏览器
    port: 8080, // 监听的端口
    hot: true,  // 是否启动模块代码热更新
    hotOnly: true, // 是否只刷新一次浏览器
  },
  // 配置编译的各模块 loader
  module: {
    noParse: /es6-promise\.js$/, // avoid webpack shimming process
    rules: [
      {
        test: /\.(js|vue)$/,
        loader: 'eslint-loader',
        enforce: 'pre',
        include: [path.resolve(__dirname, '../src/')],
        options: {
          formatter: require('eslint-friendly-formatter')
        }
      },
      // 使用 babel 把ES6转换成ES5 ,需要配合 @babel/preset-env 
      // 配置ES6转换成ES5过程中,按需补充必要代码,在js文件中,需要引入 @babel/polyfill 插件,或者使用 @babel/plugin-transform-runtime
      {
        test: /\.(js|es6)$/,
        loader: 'babel-loader',  
        exclude: /node_modules/, // 表示除了该文件外
        options:{
          presets: [['@babel/preset-env', {
            useBuiltIns: 'usage'  
          }]]
        },
      },
    ]
  },
  // 编译输出配置
  output: {
    path: path.resolve(__dirname, '../dist2'),  // 输出目录
    publicPath: '/gsh/dist/',    // 输出目录添加地址前缀
    filename: '[name].[chunkhash].js'   // 编译后输出的文件名称
  },// 使用 plugins 插件,实现编译过程中自动使用某个 html模板,以及编译前清除dist里的文件
  plugins: [
    new HtmlWebpackPlugin({
      template: 'src/index.html',  // 使用某个 html模板
    }),
    new ClearWebpackPlugin(['dist']), // 编译前清除dist里的文件
    new webpack.HotModuleReplacementPlugin(),  // 使用HMR实现模块代码热更新
  ],
}

 在生产环境和开发环境中,webpack的配置是有所区别的,可以把相同部分提取出来作为 common.js ,最后使用 webpack-merge 插件进行合并

 

 

Tree Shaking

含义为 ’摇树‘ ,其作用是在打包过程中,去除某些在项目中并没有引用的模块,  只支持 ES Module 方式, 即 import

某些在代码中引入的模块,假如在逻辑中没有使用到,那么在最后打包中不会被打包进去。

在 development 模式下,在webpack.config.js 文件中添加下列配置:

 optimization:{
    usedExports: true,
  }

在 package.js 文件中添加下列配置,表示除了某个文件外进行 Tree Shaking :

"sideEffects": ['*.css', '@babel/pollyfill']  // 表示遇到这两个模块忽略,可取值为 false

 

打包分析

可以使用webpack 官方提供的工具进行打包分析, 打开链接 https://github.com/webpack/analyse 查阅文档, 点击 analyse 位置进入分析工具,上传 stats.json 文件

在打包的时候,生成 stats.json 文件, 生成方法为 : 在 package.json 文件打包命令中添加   --profile --json > stats.json

"scripts": { "build": "webpack --profile --json > stats.json --config ./build/webpack.dev.js", },

也可以采用 webpack 提供的图形化分析工具  https://wenpack.js.org/guides     选择 Code Splitting 目录下的 Bundel Analysis

 

Code Splitting 代码分割

根据代码的应用场景和逻辑,打包的时候自动将代码分割成多个 JS 文件, 避免过大的JS 文件出现,提升页面渲染速度

同步代码分割,在webpack.config.js 文件中添加下列配置:

  optimization:{
    splitChunks: {
      chunks: 'all'  // 开启代码分割
    }
  }

异步代码(import):无需任何配置,webpack会自动进行代码分割

chunks 取值 all , 表示同步代码和异步代码都进行代码分割, 默认取值是 async , 表示只对异步代码进行分割

关于代码分割,webpack 推荐使用的是 async 的方式,这个涉及到页面的代码使用率,在浏览器控制台中, 使用 command + shift + p 的方式,搜索 Coverage 查看页面代码使用率

对于页面渲染速度的优化,使用代码缓存,并不能解决首屏加载速度的问题,应该尽量提升页面代码使用率,对于暂未使用到的代码逻辑,采用懒加载的方式。如页面调用的某个方法,方法内的逻辑在未被调用时就是多余的,可以采用异步的方法进行懒加载。

使用 webpack 里的 Prefetching / Preloading实现代码的懒加载 ,  在引入代码逻辑的时候添加  /*webpackPrefetch: true*/

例子:将某个方法里的逻辑 导出, 在调用时再作为模块导入

// 新建 click.js 文件,将方法的执行逻辑导出
function handleClick() {
  const el = document.getElementById('test')
  el.innerHTML = '点击页面后生成'
}

export default handleClick;

// 在 main.js 文件中,方法导入执行逻辑
document.addEventListener('click', () => {
  import(/*webpackPrefetch: true*/ './click.js').then(({default: handleClick}) => {
    handleClick()
  })
})

 

PWA 

全称 Progressive Web Application ,  这是一项新的技术,可以在用户进入页面的时候,缓存页面内容。当服务器故障后,用户重新进入这个页面的时候,可以利用缓存正常显示页面。

在webpack 里,可以使用 workbox-webpack-plugin 插件实现。

const WorkboxPlugin = require('workbox-webpack-plugin')

// 在 plugins 添加下列配置
    new WorkboxPlugin.GenerateSw({
      clientsClaim: true,
      skipWaiting: true
    })

 

 

VUE 多页面打包webpack配置

思路:多配置一个main的文件,用于webpack入口使用, 然后路由的导向也应该默认指向新组件,最后通过webpack构建出一个新的独立的html文件。

 

缺点:生成多个html会new出多个vue实例,文件大小应该存在优化空间。

 

*注意:以下配置建议在**master分支**中进行(sit分支也可以,但是以下配置的prod相关文件需要换成配置到dev),因为在develop分支中配置有可能导致dev环境构建的过程没有找到analysis模块而无法yarn dev在本地跑通项目,影响开发。当然也可以再dev中配置成可在dev环境下忽略analysis.ts环境,这个看个人需求。

 

> 具体做法如下

 

1. 修改webpack入口文件 <u>webpack.base.conf.js</u>

 

/** 修改entry配置项 */
entry: {
style: './src/style/app.scss', // 不变
app: './src/main.ts', //不变, 这个是index.html的组件
analysis: './src/analysis.ts'
// analysis是新增的模块名字(名字自定义,项目中因为是分析界面模块所以取名为为analysis)
// 如果还有多个其他页面,可以继续添加模块。。。
// P.S. 注意是模块不是组件,例如个analysis模块中实际包含ValueAnalysis,ValueAnalysisBar,ValueAnalysisType等组件,但是不必引入。
// P.S. 最后build打包的时候记得放出所有的模块
}

 

 

2. 新增<u>analysis.ts</u>文件

 

/** 和main.src同级,创建analysis.ts文件,注意文件名字是对应上面的./src/analysis.ts文件 */
// analysis.ts
import Vue from 'vue'

// register plugins hooks fo vue component
import 'common/registerHooks'

import * as svgicon from 'vue-svgicon'
// import all icons
import 'components/icons'

import App from 'pages/App'

Vue.use(svgicon, {
tagName: 'icon'
})

new Vue({
el: '#app',
render: h => h(App)
})

// 内容基本上和main.src一样, 但是注意router有所变化,这里router导入了一个新的路由文件routerAnalysis

 

 

3. 配置<u>build/config/index.js</u>文件

 

// 配置build中的文件输出路径,当然也可以不配置然后在下一步中直接书写文件路径,但是统一比较方便维护
build: {
index: path.resolve(__dirname, `../../dist/${env}/index.html`), // 默认的
analysis: path.resolve(__dirname, `../../dist/${env}/analysis.html`), //新加的模块


...
...
// 其他配置项不变
}

 

 

4. 配置<u>webpack.prod.conf.js</u>文件

 

> 配置输出多个html文件

 

/** 用HTMLWebpackPlugin生成多个文件 */


// 原本的htmlWebpackPlugin配置
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'build/tpl/index.html',
inject: true,
dllName,
assetsPublicPath: config.build.assetsPublicPath,
staticHost: '',
minify: {
removeComments: true,
collapseWhitespace: true
},
excludeChunks: ['analysis'], // index.html没有用到analysis模块的内容
chunksSortMode: 'dependency'
}),
// 想要生成多少不同的html就配置多少个new HtmlWebpackPlugin
new HtmlWebpackPlugin({
filename: config.build.analysis, // 生成的新的文件位置,步骤4中配置的路径
template: 'build/tpl/index.html', // html依据模板,可以沿用index.html或者另外写一个,看具体需求
inject: true,
dllName,
assetsPublicPath: config.build.assetsPublicPath,
staticHost: '',
minify: {
removeComments: true,
collapseWhitespace: true
},
excludeChunks: ['app'], // 该模块没有用到app模块中的组件
chunksSortMode: 'dependency'
}),

 

 

完成配置后的内容,使用yarn build, 选deploy就可构建生成所需的多个html。

 

posted @ 2019-12-16 15:50  嘉爷  阅读(980)  评论(0编辑  收藏  举报