Skip to content

生产环境 webpack 最基础的配置 #3

Open
@shirleyMHao

Description

@shirleyMHao

本文只讨论webpack做为打包工具,生成生产环境所必须的js、css的基本配置

具体实现如下几项:

  1. 静态处理: 包括css和js 压缩打包,以及css的抽取,es6语法支持
  2. 图片处理:小图改为data uri
  3. 静态文件注入html

目录结构如下:

image
下面我们一条一条的说如何达成目标:

首先是 webpack基本配置(entry & output)

    const path = require('path');
    var assetsPath = function (_path) {
        var assetsSubDirectory = 'static'
        return path.posix.join(assetsSubDirectory, _path)
    }
    module.exports = {
       entry: './SRC/main.js',  //指定入口文件
       output: {
            filename: assetsPath('src/main.[hash:7].js'), // 生成文件名
            path: path.resolve(__dirname, 'dist')  // 生成文件根目录
        }
    }

静态文件处理:

- 处理css:

  1. 基础:

    一般来说需要css-loader 和 style-loader。由于webpack的入口文件必须是js,我们一般需要在js中通
    过import 引入css源文件,css-loader用于解析css文件,style-loader用于将解析后的css代码嵌入到js
    中。

module: {
    rules: [
     {
        test: /\.css$/,
        use: [ 'style-loader', 'css-loader' ]
      }
    ]
}
  1. 将css抽取为独立文件

    经过css-loader和style-loader的处理之后,css文件被成功插入到js中。这种做法存在的问题是,如果css过大,会导致js单文件过大,因此我们需要将css文件单独抽取出来生成独立文件。
    我们采用extract-text-webpack-plugin 插件。它会将所有的入口 chunk(entry chunks)中引用的 *.css,移动到独立分离的 CSS 文件。因此,你的样式将不再内嵌到 JS bundle 中,而是会放到一个单独的 CSS 文件(即 styles.css)当中。 如果你的样式文件大小较大,这会做更快提前加载,因为 CSS bundle 会跟 JS bundle 并行加载来实现css文件的抽取。
    下图是官方提供优缺点对比
    image

    使用该插件,我们需要在已有的loader,创建一个提取loader
    处理css的rules变更为:

const ExtractTextPlugin = require("extract-text-webpack-plugin");
module: {
    rules: [
     {
        test: /\.css$/,
        use:  ExtractTextPlugin ({
            fallback: 'style-loader',
            use: 'css-loader'
        })
      }
    ]
}

之后在plugin中指定抽取文件的生成目录和文件名了:

plugins: {
    new ExtractTextPlugin({
      filename: assetsPath('css/[name].[contenthash].css')
    })
}
 至此我们完成了css静态文件的打包和抽取。

处理js:

  1. 解析js

:支持es6语法,引入了babel-loader

module:{
    rules:[
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        use: {
          loader: 'babel-loader'
        }
      }
}
  1. 压缩js :

webpack 自带uglifyjs插件:

plugins: [
new webpack.optimize.UglifyJsPlugin({
      compress: { //压缩
        warnings: false
      },
      sourceMap: true //生成sourceMap
    })
]

处理图片

原则上使用url-loader和file-loader都可以。url-loader可以将低于limit的图片编译为data uri插入css,但url-loader是基于file-loader的,所以我们把两者结合起来一起使用。

module:{
    rules:[
    {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000, //低于10000的图片编译为data uri
          name: assetsPath('img/[name].[hash:7].[ext]')
        }
      }
  ]
}

html处理

html-webpack-plugin插件根据模板生成编译后的html文件,并将编译后的静态资源注入html

plugins:[
new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'SRC/index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
      }
    })
]

总结

package.json

"scripts": {
    "build": "webpack"
  },
"devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-env": "^1.6.1",
    "css-loader": "^0.28.9",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^1.1.6",
    "html-webpack-plugin": "^2.30.1",
    "style-loader": "^0.20.1",
    "url-loader": "^0.6.2",
    "webpack": "^3.10.0"
  }

webpack.config.js

const path = require('path');
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
assetsPath = function (_path) {
  var assetsSubDirectory = 'static'
  return path.posix.join(assetsSubDirectory, _path)
}
module.exports = {
  entry: './SRC/main.js',
  output: {
    filename: assetsPath('src/main.[hash:7].js'),
    path: path.resolve(__dirname, 'dist')
  },
  module:{
    rules:[
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        use: {
          loader: 'babel-loader'
        }
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        })
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: assetsPath('img/[name].[hash:7].[ext]')
        }
      },
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'SRC/index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
      }
    }),
    new ExtractTextPlugin({
      filename: assetsPath('css/[name].[contenthash].css')
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      },
      sourceMap: true
    })
  ]
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions