前端面试基础必备

webpack打包

2018-09-09  本文已影响28人  puxiaotaoc

一、一个常见的webpack配置文件

// 一个常见的webpack配置文件
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
        entry: __dirname + "/app/main.js", //已多次提及的唯一入口文件
        output: {
            path: __dirname + "/build",
            filename: "bundle-[hash].js"
        },
        devtool: 'none',
        devServer: {
            contentBase: "./public", //本地服务器所加载的页面所在的目录
            historyApiFallback: true, //不跳转
            inline: true,
            hot: true
        },
        module: {
            rules: [{
                    test: /(\.jsx|\.js)$/,
                    use: {
                        loader: "babel-loader"
                    },
                    exclude: /node_modules/
                }, {
                    test: /\.css$/,
                    use: ExtractTextPlugin.extract({
                        fallback: "style-loader",
                        use: [{
                            loader: "css-loader",
                            options: {
                                modules: true,
                                localIdentName: '[name]__[local]--[hash:base64:5]'
                            }
                        }, {
                            loader: "postcss-loader"
                        }],
                    })
                }
            }
        ]
    },
    plugins: [
        new webpack.BannerPlugin('版权所有,翻版必究'),
        new HtmlWebpackPlugin({
            template: __dirname + "/app/index.tmpl.html" //new 一个这个插件的实例,并传入相关的参数
        }),
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.optimize.UglifyJsPlugin(),
        new ExtractTextPlugin("style.css")
    ]
};

二、loader和plugin的区别

loader

       loader相当于一个转换器,操作的是文件,可以将A文件进行编译形成B文件,例如将A.scss或A.less转变成B.css,是单纯的文件转换过程;

       Loader是webpack最重要的功能之一,Loader能够让webpack处理不同的文件,它可以将所有类型的文件转换成webpack能够处理的有效模块,然后利用webpack的打包能力,对他们进行处理,即将所有类型的文件转换成应用程序的依赖图可以直接引用的模块;

       1)loader可以将sass,less文件的写法转换成css,而不再使用其他转换工具;
       2)loader可以将ES6或ES7的代码转换成大多数浏览器兼容的JS代码;
       3)loader可以将React中的JSX转换成JavaScript代码;

       webpack中的Loader有两个目标:
       1)识别出应该被对应的loader进行转换的文件(使用test属性);
       2)转换这些文件,从而使其能够被添加到依赖图中(并最终添加到bundle中)(使用use属性);

       用法:Loader需要单独安装,需要什么Loader就使用npm安装即可,并对应webpack.config.js中的module属性:

module:{
  rules: [{
       test:  // 用于匹配处理文件的扩展名的表达式,必须
       use:  // loader名称,就是要使用的模块名,必须
       include/exclude: // 手动添加必须处理的文件(夹)或屏蔽不需要处理的文件(夹),可选
       query:  // 为loader提供额外的设置选项,可选
  }]
}

// use有三种写法:
// 方法一:直接用use:
use:['style-loader','css-loader']

// 方法二:将use换成loader:
loader:['style-loader','css-loader']

// 方法三:使用use + loader:
module: {
        rules: [{
            test: /\.css$/,
            use: ['style-loader', 'css-loader']
          },
          {
            test: /\.css$/,
            use: [{
                loader: 'style-loader'
              },
              {
                loader: 'css-loader',
                options: {
                  modules: true
                }
              }]
           }]
         }
plugin

       plugin相当于一个扩展器,它丰富了webpack本身,针对loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,执行广泛的任务;

       loader被用于转换某些类型的模块,而plugin则可以用于执行广泛的任务,插件的范围包括从打包优化和压缩,一直到重新定义环境中的变量,插件接口功能极其强大,可以用来处理各种各样的任务,plugin通过对节点的监听,从而找到合适的节点对文件做适当的处理;

run:开始编译
make:从entry开始递归分析依赖并对依赖进行build
build-moodule:使用loader加载文件并build模块
normal-module-loader:对loader加载的文件用acorn编译,生成抽象语法树AST
program:开始对AST进行遍历,当遇到require时触发call
require:事件
seal:所有依赖build完成,开始对chunk进行优化(抽取公共模块、加hash等)
optimize-chunk-assets:压缩代码
emit:把各个chunk输出到结果文件

       想要使用一个插件,只需要require它,然后将它添加到plugins数组中,多数插件可以通过选项自定义,也可以在一个配置中因为不同目的而多次使用同一个插件,这时需要通过使用new操作符来创建它的一个实例;webpack插件是一个具有apply属性的JavaScript对象,apply属性会被webpack compiler调用,并且compiler对象可在整个编译周期访问;由于插件可以携带参数/选项,必须在webpack配置中,向plugins属性传入new实例;

// webpack.config.js文件头部引入插件
const uglify = require('uglifyjs-webpack-plugin');
const htmlPlugin= require('html-webpack-plugin');

// 插件配置
plugins:[
   new uglify(),
   new htmlPlugin({
      minify:{
        removeAttributeQuotes: true
      },
      hash: true,
      template: './src/index.html'
    }),
],

       (1)JS 压缩:webpack中JS压缩使用的是 uglifyjs-webpack-plugin插件;

const uglify = require('uglifyjs-webpack-plugin');
plugins: [
   new uglify();
]

       注意:在开发环境中使用该插件会报错,因为在开发预览时需要明确报错行数和错误信息,所以不需要对JS压缩,而生产环境中才会对JS压缩,devServer用于开发环境,而压缩JS用于生产环境,在开发中做生产环境的事情,所以会报错;

       (2)打包HTML:要将 HTML 文件从 src 目录下打包到 dist 目录下,需要借助 html-webpack-plugin 插件,该插件需要安装;

npm install html-webpack-plugin --save-dev

// 配置:
const htmlPlugin = require('html-webpack-plugin');
plugins: [
   new htmlPlugin({
      minify: { // 对HTML文件进行压缩
        removeAttributeQuotes: true // 去除属性的双引号
      },
      hash: true, // 为了避免缓存js,加入 hash
      template: './src/index.html' // 要打包的HTML模板路径和文件名称
   })
]

三、webpack-dev-server和http服务器如nginx有什么区别?

        webpack-dev-server 的原理:正向代理隐藏了真实的客户端,而反向代理隐藏了真实的服务器,webpack-dev-server 扮演了一个代理服务器的角色,由于服务器之间通信不会存在前端常见的同源策略,这样当请求 webpack-dev-server 时,它会从真实的服务器中请求数据,然后将数据发送给浏览器;
        webpack-dev-server 主要是启动了一个使用express的Http服务器,启动webpack-dev-server后,你在目标文件夹中是看不到编译后的文件的,实时编译后的文件都保存到了内存当中,因此使用webpack-dev-server进行开发的时候看不到编译后的文件;
        webpack-dev-server 使用内存来存储webpack开发环境下的打包文件,并且可以使用模块热更新,他比传统的http服务对开发更加简单高效;

var server = new WebpackDevServer(compiler, {
  contentBase: "/path/to/directory",
  //content-base 配置 
  hot: true,
  //开启 HMR,由 webpack-dev-server 发送 "webpackHotUpdate" 消息到客户端代码
  historyApiFallback: false,
  //单页应用 404 转向 index.html
  compress: true,
  //开启资源的 gzip 压缩
  proxy: {
    "**": "http://localhost:9090"
  },
  //代理配置,来源于 http-proxy-middleware
  setup: function(app) {
     //webpack-dev-server 本身是 Express 服务器可以添加自己的路由
    // app.get('/some/path', function(req, res) {
    //   res.json({ custom: 'response' });
    // });
  },
  //为 Express 服务器的 express.static 方法配置参数 http://expressjs.com/en/4x/api.html#express.static
  staticOptions: {
  },
  //在 inline 模式下用于控制在浏览器中打印的 log 级别,如`error`, `warning`, `info` or `none`.
  clientLogLevel: "info",
  //不在控制台打印任何 log
  quiet: false,
  //不输出启动 log
  noInfo: false,
  //webpack 不监听文件的变化,每次请求来的时候重新编译
  lazy: true,
  //文件名称
  filename: "bundle.js",
  //webpack 的 watch 配置,每隔多少秒检查文件的变化
  watchOptions: {
    aggregateTimeout: 300,
    poll: 1000
  },
  //output.path 的虚拟路径映射
  publicPath: "/assets/",
  //设置自定义 http 头
  headers: { "X-Custom-Header": "yes" },
  //打包状态信息输出配置
  stats: { colors: true },
  //配置 https 需要的证书等
  https: {
    cert: fs.readFileSync("path-to-cert-file.pem"),
    key: fs.readFileSync("path-to-key-file.pem"),
    cacert: fs.readFileSync("path-to-cacert-file.pem")
  }
});
server.listen(8080, "localhost", function() {});
// server.close();

        bundle是由webpack打包出来的文件,chunk是指webpack在进行模块的依赖分析的时候,代码分割出来的代码块;module是开发中的单个模块;

        Tree-shaking是指在打包中去除那些引入了,但是在代码中没有被用到的那些死代码,在webpack中Tree-shaking是通过uglifySPlugin来Tree-shaking JS,Css需要使用Purify-CSS;

参考链接:
入门webpack,看这篇就够了
webpack3-loader和plugin的概念理解
webpack-dev-server 核心概念

上一篇下一篇

猜你喜欢

热点阅读