webpack打包

概念

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

可以从***这里***了解更多关于 JavaScript 模块和 webpack 模块的信息。

从 webpack v4.0.0 开始,可以不用引入一个配置文件。然而,webpack 仍然还是高度可配置的。在开始前你需要先理解四个核心概念

  • 入口(entry)
  • 输出(output)
  • loader
  • 插件(plugins)

本文档旨在给出这些概念的高度概述,同时提供具体概念的详尽相关用例。

入口(entry)

**入口起点(entry point)**指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。

每个依赖项随即被处理,最后输出到称之为 bundles 的文件中。
可以通过在 ***webpack 配置***中配置 entry 属性,来指定一个入口起点(或多个入口起点)。默认值为 ./src。
接下来我们看一个 entry 配置的最简单例子:
webpack.config.js

module.exports = {
  entry: './path/to/my/entry/file.js'
};

根据应用程序的特定需求,可以以多种方式配置 entry 属性。从入口起点章节可以了解更多信息。

出口(output)

output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。你可以通过在配置中指定一个 output 字段,来配置这些处理过程:

webpack.config.js

const path = require('path');

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  }
};

在上面的示例中,我们通过 output.filename 和 output.path 属性,来告诉 webpack bundle 的名称,以及我们想要 bundle 生成(emit)到哪里。可能你想要了解在代码最上面导入的 path 模块是什么,***它是一个 Node.js 核心模块***,用于操作文件路径。

你可能会发现术语生成(emitted 或 emit)贯穿了我们整个文档和***插件 API***。它是“生产(produced)”或“释放(discharged)”的特殊术语。

output 属性还有***更多可配置的特性***,如果你想要了解更多关于 output 属性的概念,你可以通过***阅读概念章节***来了解更多。

loader

loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效***模块***,然后你就可以利用 webpack 的打包能力,对它们进行处理。

本质上,webpack loader 将所有类型的文件,转换为应用程序的依赖图(和最终的 bundle)可以直接引用的模块。

注意,loader 能够 import 导入任何类型的模块(例如 .css 文件),这是 webpack 特有的功能,其他打包程序或任务执行器的可能并不支持。我们认为这种语言扩展是有很必要的,因为这可以使开发人员创建出更准确的依赖关系图。
在更高层面,在 webpack 的配置中 loader 有两个目标:

  1. test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。
  2. use 属性,表示进行转换时,应该使用哪个 loader。
    webpack.config.js
const path = require('path');

const config = {
  output: {
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader' }
    ]
  }
};

module.exports = config;

以上配置中,对一个单独的 module 对象定义了 rules 属性,里面包含两个必须属性:testuse。这告诉 webpack 编译器(compiler) 如下信息:

“嘿,webpack 编译器,当你碰到「在 require()/import语句中被解析为 ‘.txt’ 的路径」时,在你对它打包之前,先使用 raw-loader 转换一下。”

重要的是要记得,在 webpack 配置中定义 loader 时,要定义在 module.rules 中,而不是 rules。然而,在定义错误时 webpack 会给出严重的警告。为了使你受益于此,如果没有按照正确方式去做,webpack 会“给出严重的警告”

loader 还有更多我们尚未提到的具体配置属性。

了解更多!

插件(plugins)

loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。***插件***的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。

想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建它的一个实例。

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
const webpack = require('webpack'); // 用于访问内置插件

const config = {
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader' }
    ]
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

module.exports = config;

webpack 提供许多开箱可用的插件!查阅我们的***插件列表***获取更多信息。

在 webpack 配置中使用插件是简单直接的,然而也有很多值得我们进一步探讨的用例。

了解更多!

模式

通过选择 developmentproduction 之中的一个,来设置 mode 参数,你可以启用相应模式下的 webpack 内置的优化

module.exports = {
  mode: 'production'
};

了解更多!

案例:
package.json的相关配置:

{
  "name": "web",
  //
  "version": "1.0.0",
  "description": "web项目",
  "main": "./webapp/WEB-INF/views/index.jsp",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --config webpack.config.js",
    "dev-build": "webpack --config webpack.dev.config.js --color --progress",
    "watch": "webpack --watch --hot --color --progress --config webpack.dev.config.js"
  },
  "author": "ctt",
  "license": "ISC",
  "dependencies": {
    "antd": "^3.1.1",
    "axios": "^0.17.1",
    "babel-polyfill": "^6.26.0",
    "classnames": "^2.2.5",
    "copy-to-clipboard": "^3.0.8",
    "dva": "^2.1.0",
    "dva-loading": "^1.0.4",
    "echarts": "^4.1.0",
    "echarts-for-react": "^2.0.13",
    "highcharts": "^6.0.7",
    "highcharts-react-official": "^0.0.1",
    "history": "^4.7.2",
    "lodash": "^4.17.4",
    "lodash-decorators": "^4.5.0",
    "lodash.clonedeep": "^4.5.0",
    "moment": "^2.20.1",
    "numeral": "^2.0.6",
    "prop-types": "^15.6.0",
    "qs": "^6.5.1",
    "query-string": "^5.0.1",
    "react": "^16.2.0",
    "react-container-query": "^0.10.0",
    "react-document-title": "^2.0.3",
    "react-dom": "^16.2.0",
    "react-fittext": "^1.0.0",
    "universal-cookie": "^2.1.2"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-plugin-add-module-exports": "^0.2.1",
    "babel-plugin-import": "^1.6.3",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    "bundle-loader": "^0.5.5",
    "clean-webpack-plugin": "^0.1.17",
    "css-loader": "^0.28.8",
    "extract-text-webpack-plugin": "^3.0.2",
    "compression-webpack-plugin":"^1.1.11",
    "file-loader": "^1.1.6",
    "less": "^2.7.3",
    "less-loader": "^4.0.5",
    "postcss-cssnext": "^3.0.2",
    "postcss-loader": "^2.0.10",
    "react-hot-loader": "^4.0.0-beta.12",
    "style-loader": "^0.19.1",
    "uglifyjs-webpack-plugin": "^1.1.6",
    "url-loader": "^0.6.2",
    "webpack": "^3.10.0",
    "webpack-merge": "^4.1.1"
  }
}

webpack.common.config.js是webpack的入口和出口的基础配置:

const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');//清除打包的文件插件
const webpack = require('webpack');

commonConfig = {
    //入口配置
    entry: {
      app: [
        "babel-polyfill",
        path.join(__dirname, './src/main/js/index.js'),
      ],
      //需要打包一起的公共模块
      vendor: ['antd', 'react','dva'],
    },
    //出口配置
    output: {
      path: path.join(__dirname, './src/main/webapp/static/build'),
      filename: 'bundle.js',
      publicPath: "/static/build/"
    },
    //module配置
    module: {
        //url-loader模块
        rules: [{
            test: /\.(png|jpg|gif)$/,
            use: [{
                loader: 'url-loader',
                options: {
                    limit: 4096,
                    name : 'images/[hash].[ext]'
                }
            }],
            exclude: [
              path.resolve(__dirname, "./src/main/js/components/Emoji/basic/images")
            ],
        },
        //file-loader模块
        {
          test: /\.(png|gif|jpg|svg|jpeg)$/i,
          include: [
            path.resolve(__dirname, "./src/main/js/components/Emoji/basic/images")
          ],
          use: {
            loader: 'file-loader',
            options : {
                 name : 'emoji/image/[hash].[ext]'
            }
          }
         }]
    },

    plugins: [
        new CleanWebpackPlugin(['./src/main/webapp/static/build']),
        //是将公共模块进行打包一起(打包优化方案之一)
        new webpack.optimize.CommonsChunkPlugin({
          name: 'vendor',
          filename: "vendor.js",
          minChunks: 3,
        }),
    ],
};
module.exports = commonConfig;

webpack.dev.config.js这个是本地开发用的webpack打包方案

const merge = require('webpack-merge');
const path = require('path');
const commonConfig = require('./webpack.common.config.js');
const theme = require("./src/main/js/theme");

const config = {
  devtool: 'inline-source-map',

  module: {
    rules: [{
      test: /\.js$/,
      use: ['babel-loader?cacheDirectory=true'],
      include: path.join(__dirname, './src/main/js')
    }, {
      test: /\.css$/,
      use: ["style-loader", "css-loader?modules&localIdentName=[local]-[hash:base64:5]", "postcss-loader"],
      exclude: /node_modules/
    }, {
      test: /\.css$/,
      use: ["style-loader", "css-loader", "postcss-loader"],
      include: /node_modules/
    }, {
      test: /\.less$/,
      use: ["style-loader", "css-loader?modules&localIdentName=[local]-[hash:base64:5]", "postcss-loader", `less-loader?{"modifyVars":${JSON.stringify(theme)}}`],
      exclude: /node_modules/
    }, {
      test: /\.less$/,
      use: ["style-loader", "css-loader", "postcss-loader", `less-loader?{"modifyVars":${JSON.stringify(theme)}}`],
      include: /node_modules/
    }]
  }
};
module.exports = merge(commonConfig, config);

webpack.config.js 是生产环境的webpack打包配置

const merge = require('webpack-merge');
const path = require('path');
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');//js进行压缩
const ExtractTextPlugin = require("extract-text-webpack-plugin");//css打包整合一起优化
var CompressionPlugin = require("compression-webpack-plugin");//通过gzip进行压缩优化
const commonConfig = require('./webpack.common.config.js');
const theme = require("./src/main/js/theme");
const extractCSS = new ExtractTextPlugin({
  filename: '[name].css',
  allChunks:true
});
const config = {
  devtool: 'none',
  module: {
    //js支持ES5的打包loader
    rules: [{
      test: /\.js$/,
      use: ['babel-loader'],
      include: path.join(__dirname, './src/main/js')
    }, {
      test: /\.css$/i,
      use: extractCSS.extract({
            fallback: 'style-loader',
            use: [{
              loader: 'css-loader',
              options:{
                localIdentName:'[local]-[hash:base64:5]',
                minimize:true,
                modules:true,
              }
            }, {
              loader: "postcss-loader"
            }]
          }
      ),
      exclude: /node_modules/
    }, {
      test: /\.css$/i,
      use: extractCSS.extract({
        fallback: 'style-loader',
        use: [{
          loader: 'css-loader'
        }, {
          loader: "postcss-loader"
        }]
      }),
      include: /node_modules/
    }, {
      test: /\.less$/i,
      use: extractCSS.extract({
        use: [{
          loader: "css-loader",
          options:{
            localIdentName:'[local]-[hash:base64:5]',
            minimize:true,
            modules:true,
          }
        }, {
          loader: "postcss-loader"
        }, {
          loader: `less-loader?{"modifyVars":${JSON.stringify(theme)}}`
        }],
        fallback: "style-loader"
      }),
      exclude: /node_modules/
    }, {
      test: /\.less$/i,
      use: extractCSS.extract({
        use: [{
          loader: "css-loader"
        }, {
          loader: "postcss-loader"
        }, {
          loader: `less-loader?{"modifyVars":${JSON.stringify(theme)}}`
        }],
        fallback: "style-loader"
      }),
      include: /node_modules/
    }]
  },
  plugins: [
    new UglifyJSPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production')
      }
    }),
    extractCSS,
    new CompressionPlugin({
      asset: "[path].gz[query]",
      algorithm: "gzip",
      test: /\.js/,
      threshold: 20480,
      minRatio: 0.8,
    })
  ]
};
module.exports = merge(commonConfig, config);

这个是整合webpack的官网概念描述和自己项目对其打包进行优化的配置。用于以后web项目的页面打包的借鉴

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值