webpack构建技巧之生产篇

本文接前篇 webpack构建技巧之开发篇,但可独立使用。

项目目录:

一、入口

入口与开发篇相同

function resolve(dir) {
  return path.join(__dirname, '..', dir) //返回的是项目目录下的文件夹
} 
module.exports = {
  entry: resolve('src/main.js')
}

二、出口

出口与开发篇有点差别

  output: {
    path: resolve('dist'),
    filename: 'static/js/[name].[hash:8].js',
    chunkFilename: 'static/js/[name].[hash:8].chunk.js',
    publicPath: "./"
  },

关于publicPath:

公共路径,它会在你所有的路径前加指定参数。看图:

这是 publicPath = ' ./ ' 下的文件路径

这是默认的,也就是 publicPath = ' ' 下的文件路径:

 

三、module

其他的处理除css外与开发篇相同,以下就仅仅把代码贴上:

     {
        test: /\.(htm|html)$/i,
        use: [{
          loader: 'html-withimg-loader'
        }]
      },
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        include: /\src/,
        use: {
          loader: 'babel-loader',
        }
      },
      {
        test: /\.(png|jpg|gif)$/,
        use: [{
          loader: 'url-loader',
          options: {
            limit: 10000,
            name: 'static/img/[name].[hash:8].[ext]',
          }
        }]
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: 'static/media/[name].[ext]'
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: 'static/fonts/[name].[ext]'
        }
      },

对于css的处理:

我们更多的情况下是会引入外部的css文件,这里处理的目的就是把多个css文件处理成一个文件并用外联的方法引入。

首先,提取css,webpack4+用 mini-css-extract-plugin 这个插件,其他使用 extract-text-webpack-plugin 这个插件。

webpack4+:

在前面引入插件

//webpack 4+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

//webpack 4-
const ExtractTextPlugin = require('extract-text-webpack-plugin')

    {    
        test: /\.(css|less)$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '../../' //这个publicPath是为了解决css中引入背景图的路径问题
            }
          },
          'css-loader',
          {
            loader: require.resolve('postcss-loader'),
            options: {
              ident: 'postcss',
              plugins: () => [
                require('postcss-flexbugs-fixes'),
                autoprefixer({
                  browsers: [
                    '>1%',
                    'last 4 versions',
                    'Firefox ESR',
                    'not ie < 9',
                  ],
                  flexbox: 'no-2009',
                }),
              ],
            },
          },
          'less-loader'
        ],

      },

webpack4-:

     {
                test: /\.(css|less)$/,
                loader: ExtractTextPlugin.extract(
                    Object.assign({
                        fallback: {
                            loader: require.resolve('style-loader'),
                            options: {
                                hmr: false,
                            },
                        },
                        publicPath:'../../', //接css引入背景图的路径问题
                        use: [
                          {
                                loader: require.resolve('css-loader'),
                                options: {
                                    importLoaders: 1,
                                    minimize: true
                                },
                            },
                            {
                                loader: require.resolve('postcss-loader'),
                                options: {
                                    ident: 'postcss',
                                    plugins: () => [
                                        require('postcss-flexbugs-fixes'),
                                        autoprefixer({
                                            browsers: [
                                                '>1%',
                                                'last 4 versions',
                                                'Firefox ESR',
                                                'not ie < 9',
                                            ],
                                            flexbox: 'no-2009',
                                        }),
                                    ],
                                },
                            },
                            {
                                loader: require.resolve('less-loader'),
                            },
                        ],
                    }, )
                ),
            },

然后在plugins中生成css文件:

new MiniCssExtractPlugin({
      filename: 'static/css/[name].[hash:8].css'
    }),
new ExtractTextPlugin({
      filename: 'static/css/[name].[hash:8].css'
    }),

关于publicPath:

假设你在开发中写如如下背景图样式:

显然这在线上环境中是那不到的,因为这个路径是在css文件中被引用的,你得加上相对路径参数,在我的文件夹目录下是这样的:

各个文件夹结构不相同,你可以灵活选择。


 

 

三、plugins

这里用于处理并压缩文件:

js:

在webpack4-中使用 uglifyjs-webpack-plugin这个插件,然后直接在plugins中使用就ok

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

plugins: {
  new UglifyJsPlugin()
}

optimization(webpack4+)

在webpack4+中移除了 uglifyjs-webpack-plugin 方法,采用optimization中对js压缩,提取,去重,方法如下:

optimization: {
    minimize: true, //压缩js,默认使用uglifyjs-webpack-plugin插件
    splitChunks: {
      cacheGroups: { //定义规则
        vendors: { //提取node_modules中对js生成chunk-vndord文件夹
          name: 'chunk-vendors', 
          test: /[\\\/]node_modules[\\\/]/,
          priority: -10,
          chunks: 'all'
        },
        common: { //提取公共部分js生成chunk-common文件夹
          name: 'chunk-common',
          minChunks: 2,
          priority: -20,
          chunks: 'all',
          reuseExistingChunk: true
        },
        styles: { //提取less或css合成一个layout.css文件 
          name: 'layout',
          test: /\.(less|css)$/,
          chunks: 'all',
          minChunks: 1,
          reuseExistingChunk: true,
          enforce: true
        }
      }
    }
  },


最后生成的文件夹目录结构如下图:

css:

提取css已经在module中说明,这里说一下压缩:安装插件 optimize-css-assets-webpack-plugin 

const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');



 new OptimizeCSSPlugin({
      cssProcessorOptions: {safe: true, map: {inline: false}}
     }),

html:

 new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html', //本地自定义模板
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true,
      },
      chunksSortMode: 'dependency' //定义引入文件顺序,按依赖排序
    }),

其他:

//复制静态文件
new CopyWebpackPlugin([{
      from: resolve('static'),
      to: resolve('dist/static'),
      ignore: ['.*']
    }]),
//生成文件索引文件
 new ManifestPlugin({
      fileName: 'asset-manifest.json',
    }),

最后,由于每次修改后打包加了hash值,每次文件加都不一样,就会造成每打包一次就会新增加一个相同文件,类似于这样:

我们在打包之前先做一步,就是把现有的dist文件夹移除掉,新建一个build.js文件,这里用到一个插件 rimraf

const webpack = require('webpack');
const path = require('path');
const webpackConfig = require('./webpack.pro.conf');
const rm = require('rimraf');


function resolve(dir) {
  return path.join(__dirname, '..', dir)
}

rm(resolve('dist'), err => {
  if (err) throw err
  webpack(webpackConfig, err => {
    if (err) throw  err
  })
})

构建基本完成,改下命令行:

//package.json
"build": "node config/build.js"

npm run build 就可以生成你的项目生产版本。

这可能是一个最简单的版本,还可以做很多优化的地方,webpack中还有很多有趣的插件,希望看完不吝指正,多谢!

完整版本请移步:https://github.com/linxner/webpackENV

最后,附上所有webpack.pro.conf.js代码:

//webpack.pro.conf.js
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const autoprefixer = require('autoprefixer')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const ManifestPlugin = require('webpack-manifest-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');




function resolve(dir) {
  return path.join(__dirname, '..', dir)
}

module.exports = {
  entry: resolve('src/main.js'),

  output: {
    path: resolve('dist'),
    filename: 'static/js/[name].[hash:8].js',
    chunkFilename: 'static/js/[name].[hash:8].chunk.js',
    publicPath: "./"
  },

  module: {
    rules: [
      {
        test: /\.(htm|html)$/i,
        use: [{
          loader: 'html-withimg-loader'
        }]
      },
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        include: /\src/,
        use: {
          loader: 'babel-loader',
        }
      },
      {
        test: /\.(png|jpg|gif)$/,
        use: [{
          loader: 'url-loader',
          options: {
            limit: 10000,
            name: 'static/img/[name].[hash:8].[ext]',
          }
        }]
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: 'static/media/[name].[ext]'
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: 'static/fonts/[name].[ext]'
        }
      },
      {
        test: /\.(css|less)$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '../../'
            }
          },
          'css-loader',
          {
            loader: require.resolve('postcss-loader'),
            options: {
              ident: 'postcss',
              plugins: () => [
                require('postcss-flexbugs-fixes'),
                autoprefixer({
                  browsers: [
                    '>1%',
                    'last 4 versions',
                    'Firefox ESR',
                    'not ie < 9',
                  ],
                  flexbox: 'no-2009',
                }),
              ],
            },
          },
          'less-loader'
        ],

      },
    ],
  },

  mode: "production",

  optimization: {
    minimize: true,
    splitChunks: {
      cacheGroups: {
        vendors: {
          name: 'chunk-vendors',
          test: /[\\\/]node_modules[\\\/]/,
          priority: -10,
          chunks: 'all'
        },
        common: {
          name: 'chunk-common',
          minChunks: 2,
          priority: -20,
          chunks: 'all',
          reuseExistingChunk: true
        },
        styles: {
          name: 'layout',
          test: /\.(less|css)$/,
          chunks: 'all',
          minChunks: 1,
          reuseExistingChunk: true,
          enforce: true
        }
      }
    }
  },

  plugins: [
    new MiniCssExtractPlugin({
      filename: 'static/css/[name].[hash:8].css',
    }),

    new OptimizeCSSPlugin({
      cssProcessorOptions: {safe: true, map: {inline: false}}
    }),

    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html', //本地自定义模板
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true,
      },
      chunksSortMode: 'dependency'
    }),

    new CopyWebpackPlugin([{
      from: resolve('static'),
      to: resolve('dist/static'),
      ignore: ['.*']
    }]),

    new ManifestPlugin({
      fileName: 'asset-manifest.json',
    }),
  ],
}

猜你喜欢

转载自blog.csdn.net/linxner/article/details/86590188