Webpack学习记录

作者: 汉堡会有的 | 来源:发表于2020-04-09 13:42 被阅读0次
// 一个常见的`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('123'),
        new HtmlWebpackPlugin({
            template: __dirname + "/app/index.tmpl.html" //new 一个这个插件的实例,并传入相关的参数
        }),
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.optimize.UglifyJsPlugin(),
        new ExtractTextPlugin("style.css")
    ]
};

注:“_dirname”是node.js的一个全局变量,指向当前执行脚本所在的目录。

几个核心概念。

  • Entry: 入口,webpack执行构建的第一步将从Entry开始,可抽象成输入
  • Module: 模块,在Webpack里一切皆模块,一个模块对应一个文件。Webpack会从配置的Entry开始递归找出所有依赖的模块。
  • Chunk: 代码块,一个Chunk由多个模块组合而成,用于代码合并与分割。
  • Loader: 模块转换器,用于将模块的原内容按照需求转换成新内容。项目中需要的每个Loader都需要安装。
  • Plugin: 扩展插件,在Webpack构建流程中的特定时机注入扩展逻辑,来改变构建结果或做我们想要的事情。
  • Output: 输出结果,在Webpack经过一系列处理并得出最终想要的代码后输出结果。

Webpack在启动后会从Entry里面配置的Module开始,递归解析Entry依赖的所有Module。每找到一个Module,就会根据配置的Lodaer去找出对应的转换规则,对Module进行转换后,再解析出当前Module依赖的Module。这些模块会以Entry为单位进行分组,一个Entry及其所有依赖的Module被分到一个组也就是一个Chunk。最后,Webpack会将所有Chunk转换成文件输出。在整个流程中,Webpack会在恰当的时机执行Plugin里定义的逻辑。

DevServer

使用DevServer,DevServer会启动一个HTTP服务器用于服务网页请求,同时会帮助启动Webpack,并接收Webpack发出的文件变更信号,通过WebSocket协议自动刷新网页做到实时预览。

执行打包任务

可以在package.json里对scripts对象进行设置即可。

 {
  "scripts": {
    "start": "webpack-dev-server --open --hot --progress --colors --host localhost",
    "build": "rm -rf ./dist && webpack --progress --colors"
  },
 }

npm的start命令是一个特殊的脚本名称,其特殊性表现在,在命令行中使用npm start就可以执行其对于的命令,如果对应的此脚本名称不是start,想要在命令行中运行时,需要这样用npm run {script name}npm run build

--open --host localhost
//执行npm start后自动打开浏览器

resolve.alias && ProvidePlugin

有时候我们在项目中会需要频繁引入同一个路径的文件,如果需要引入的次数特别多,我们就得在每一次引入都要写一长串的地址,那么我们有没有什么方法可以偷点懒呢,我们可以通过调整webpack里的配置达到“偷一点小懒”的目的。

   resolve.alias这个配置项相当于为文件目录配置一个别名

使用resolve.alias配置的用法如下

module.exports = {
  entry: 
  {
    main:'./main.js',
  },
  output: {
    path:__dirname+'/dist',
    filename: '[name].js'
  },
  resolve:{
    //配置别名,在项目中可缩减引用路径
    alias: {
      vue$: 'vue/dist/vue.esm.js',
      '@': resolve('src'),
      '&': resolve('src/components'),
      'api': resolve('src/api'),
      'assets': resolve('src/assets')
    }
  },
  plugins: [
   
  ]
};

这样配置后在使用的时候就可以直接

import http from '@/utils/http'

代替

import http from 'src/utils/http'
reslove.alias可以让我们不用重复的去写一长串的路径,但是在使用的时候还是得引入,如果我们连引入都懒得引入呢?webpack为我们提供了ProvidePlugin这个帮我们解决问题的插件

那么ProvidePlugin要怎么使用呢?
webpack.config.js

const webpack = require('webpack')
module.exports = {
  entry: 
  {
    main:'./main.js',
  },
  output: {
    path:__dirname+'/dist',
    filename: '[name].js'
  },
  resolve:{
    //配置别名,在项目中可缩减引用路径
    alias: {
      
    }
  },
  plugins: [
    //提供全局的变量,在模块中使用无需用require引入
    new webpack.ProvidePlugin({
      $config: [resolve(`src/data/config/${process.env.CONFIG_ENV}.env.js`), 'default'],
    }),
  ]
};

使用的时候就可以寄直接将 $config作为一个全局变量来使用

编写一个plugin

plugin可以监听webpack处理过程中的关键事件,深度集成进webpack的编译器,可以说plugin的执行层面是整个构建过程。Plugin系统是构成webpack的主干,webpack自身也基于plugin系统搭建,webpack有丰富的内置插件和外部插件,并且允许用户自定义插件。

插件的组成部分

  • 一个javaScript命名函数,并暴露出去
  • 在插件函数的prototype上定义一个apply方法,注入complier对象
  • 指定一个绑定到webpack自身的事件钩子
  • 处理webpack内部实例的特定数据
  • 功能完成后调用webpack提供的回调
function MyPlugin(options) {}
// 2.函数原型上的 apply 方法会注入 compiler 对象
MyPlugin.prototype.apply = function(compiler) {
  // 3.compiler 对象上挂载了相应的 webpack 事件钩子 4.事件钩子的回调函数里能拿到编译后的 compilation 对象
  compiler.plugin('emit', (compilation, callback) => {
    ...
  })
}
// 1.独立的 JS 模块,暴露相应的函数
module.exports = MyPlugin

Compiler 和 Compilation

compiler对象和compilation对象是webpack插件开发中最重要的两个资源,那他们分别是什么呢?

  • compiler 对象代表了完整的 webpack 环境配置。这个对象在启动 webpack 时被一次性建立,并配置好所有可操作的设置,包括 options,loader 和 plugin。当在 webpack 环境中应用一个插件时,插件将收到此 compiler 对象的引用。可以使用它来访问 webpack 的主环境。

  • compilation 对象代表了一次资源版本构建。当运行 webpack 开发环境中间件时,每当检测到一个文件变化,就会创建一个新的 compilation,从而生成一组新的编译资源。一个 compilation 对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。compilation 对象也提供了很多关键时机的回调,以供插件做自定义处理时选择使用。

compiler 对象

compiler 即 webpack 的编辑器对象,在调用 webpack 时,会自动初始化 compiler 对象,源码如下:

// webpack/lib/webpack.js
const Compiler = require("./Compiler")

const webpack = (options, callback) => {
  ...
  options = new WebpackOptionsDefaulter().process(options) // 初始化 webpack 各配置参数
  let compiler = new Compiler(options.context)             // 初始化 compiler 对象,这里 options.context 为 process.cwd()
  compiler.options = options                               // 往 compiler 添加初始化参数
  new NodeEnvironmentPlugin().apply(compiler)              // 往 compiler 添加 Node 环境相关方法
  for (const plugin of options.plugins) {
    plugin.apply(compiler);
  }
  ...
}
compilation 对象

结合源码来理解下上面这段话,首先 webpack 在每次执行时会调用 compiler.run() (源码位置),接着追踪 onCompiled 函数传入的 compilation 参数,可以发现 compilation 来自构造函数 Compilation。

// webpack/lib/Compiler.js
const Compilation = require("./Compilation");

newCompilation(params) {
  const compilation = new Compilation(this);
  ...
  return compilation;
}

path.join()与path.resolve()的区别

path 是 node.js内置的package,用来处理路径

  • path.join([path1],[path2][,...])

    用于连接路径,对参数里的路径片段就行拼接

  • path.resolve([from...][,to])

    将to解析成绝对路径

path.resolve(_dirname, '/img')
    
console.log(_dirname) //当前文件所在文件夹的绝对路径

相关文章

  • 初探webpack小记

    webpack学习记录 安装webpack 全局安装webpack:npm install webpack -g之...

  • 前端工程化之webpack学习记录

    本文是本人正式开始学习webpack的记录文档,时间:2020-05-16,webpack版本:"webpack"...

  • webpack学习记录

    学习链接: https://doc.webpack-china.org/concepts/webpack处理css...

  • 学习webpack记录

    现在在用JavaScript练习算法题,用到大量ES6语法特性,在补充ES6语言基础的同时,实在觉得nodejs内...

  • webpack学习记录

    先从看文档开始学习,认识,学习的是webpack v4.41.0传送门:https://www.webpackjs...

  • Webpack学习记录

    注:“_dirname”是node.js的一个全局变量,指向当前执行脚本所在的目录。 几个核心概念。 Entry:...

  • 2018-06-17 webpack—js打包

    记录webpack打包学习 我现在跟着视频教程学习webpack基础打包,在最开始就遇到了问题,首先教程webpa...

  • webpack学习记录(起步)

    学习的首要在于形成闭环,所以虽然只是很累赘的复述,但也请认真对待吧~ webpack用于打包编译js模块,这样说很...

  • webpack学习记录01

    entry和output 新建一个文件夹, 进去之后安装了webpack, 和webpack-dev-server...

  • webpack学习记录02

    loaders现在盛行的语法react, 用的是独创的jsx语法,loaders参数可以让你的项目自动识别这些js...

网友评论

    本文标题:Webpack学习记录

    本文链接:https://www.haomeiwen.com/subject/atccmhtx.html