webpack4 (2) --- 核心概念

174 阅读5分钟

1.什么是loader

  当引入非js的模块时,因为webpack不能够进行翻译打包,所以要借助loader来帮webpack进行翻译打包。
  loader 用于转换某些类型的模块

1.1 loader的基本使用

  1. test 属性,识别出哪些文件会被转换。
  2. use 属性,定义出在进行转换时,应该使用哪个 loader。
module.exports = {
    entry:{
        main: './src/index.js'
    },
    output:{
        filename: 'main',
        path:path.resolve(__dirname, 'dist')
    },
    module:{
        rules:[{
            test:'/\.(jpg|png|gif)$/',
            use:[{
                loader: 'file-loader'
            }]
        }]
    }
}
    当需要loader时,我们引入Loader也需要符合webpack的规则.
    如当webpack打包到非js的静态资源时,它会在webpack.config.js的配置文件中,查看module的rules模块,看看是否有loader能够帮助它翻译它不认识的静态资源。
    第二天理解什么是loader以及为什么用它(loader的作用)就可以了

2.使用loader打包静态资源(图片篇) file-loader/url-laoder

2.1 ## Options

  1. name配置,打包名称。
  2. outputPath配置,打包路径(文件夹)
  3. limit配置, url-loader专有,如果文件小于字节限制,则以base64位的形式打包在js文件中,否则与file-loader打包无异

2.2 file-loader与url-loader的区别

url-loader与 类似 file-loader,但如果文件小于字节限制,则可以返回 DataURL

2.3代码实现

   module.exports = {
       entry:{
           main: './src/index.js'
       },
       output:{
           filename: 'main',
           path: path.resolve(__dirname, 'dist')
       },
       module:{
           rules:[{
               test:/\.(jpg|png|gif)$/,
               use:[{
                   loader: 'url-loader',
                   options:{
                       name: '[name].[ext]',
                       outputPath: 'images/',
                       limet: 20480
                   }
               }]
           }]
       }
   }

2.4 placehodlers 常用占位符

  1. [ext]: 目标文件/资源的文件扩展名。
  2. [name]: 文件/资源​​的基本名称。
  3. [path]: 资源相对于 webpack/config 的路径context
  4. [folder]: 资源所在的文件夹
  5. [<hashType>:hash:<digestType>:<length>] options.content (Buffer) 的散列(默认情况下它是散列的十六进制摘要)。 5例子
options: {
    name: '[sha512:hash:base64:7].[ext]',
},

3. loader打包静态资源样式篇(上篇)

3.1 所需的loader

  1. style-loader: 将生成的css放到head
  2. css-loader: 将多个相关联的css打包成一个
  3. scss-loader: 将scss语法翻译为css
  4. postcss-loader

image.png

3.2 增加浏览器声明的前缀

  1. 引入postcss-loader,借此生成ast
  2. 生成postcss.config.js配置文件
  3. 引入插件autoprefixer

3.3 代码的基本实现

webpack.config.js

    modele.exports = {
        mode: 'development',
        entry:{
            main: './src/index.js'
        },
        output:{
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist')
        },
        module:{
            rules:[
            {
                test:/\.(jpg|png|gif)$/,
                use:[{
                    loader: 'url-loader',
                    options:{
                        limit: 20480,
                        name: '[name][hash].[ext]',
                        outputPath: 'images/' 
                    }
                }]
            },{
                test:/\.scss$/,
                use:[
                'style-loader',
                'css-loader',
                'scss-loader',
                'postcss-loader'
                ]
            }]
        }
    }

postcss.config.js

    moudule.exports = {
        plugins:[
            require('autoprefixer')
        ]
    }

4. loader打包静态资源样式篇(下篇)

1、 importLoaders 选项允许你配置在 css-loader 之前有多少 loader 应用于 @imported 资源与 CSS 模块/ICSS 导入

2、 modules 选项启用/禁用 CSS 模块 规范并且设置基本的行为。 3. 打包文本

image.png

5.plugins初探

插件(Plugins)是用来拓展webpack功能的,它们会在整个构建过程(类似Vue生命周期)中生效,执行相关的任务。

1.html-webpack-plugin

该插件将为你生成一个 HTML5 文件, 在 body 中使用 script 标签引入你所有 webpack 生成的 bundle。 只需添加该插件到你的 webpack 配置中

2.CleanWebpackPlugin

该插件会在打包前会清空dist(具体看自己的设置)

代码演示

const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const path = require('path');

module.exports = {
  entry: 'index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'index_bundle.js',
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'src/index.html'
    }),
    new CleanWebpackPlugin(['dist'])
  ],
};

6.entry与output的基础配置与多入口打包

6.1 entry

entry: {
    main: './src/index.js',
    sub: './src/index.js'
},

6.2 output

publicPath:公共cdn 如果在编译时,不知道最终输出文件的 publicPath 是什么地址,则可以将其留空,并且在运行时通过入口起点文件中的 __webpack_public_path__ 动态设置。

__webpack_public_path__ = myRuntimePublicPath;

// 应用程序入口的其余部分
output: {
    publicPath: 'http://cdn.com.cn',
    filename: '[name].js',
    path: path.resolve(__dirname, 'dist')
}

打包结果

image.png

7 devtool

devtool 选择一种 source map 格式来增强调试过程。不同的值会明显影响到构建(build)和重新构建(rebuild)的速度。

suurce map是指一种源映射模式。

提示错误不使用source map模式

image.png

image.png 使用score map

image.png

7.1模式类型

  1. source-map :源映射
  2. cheap: 映射只到行不到字符 ++
  3. module: 第三方资源的错误
  4. eval: 在main.js中以eval来抛出错误 ++

7.2推荐使用

development: devtool: 'cheap-module-eval-source-map'

production: devtool: 'cheap-module-source-map'

8.devServer

8.1监听文件变化可自动打包的三种方式

  1. "watch": "webpack --watch" 缺点:不是服务器
  2. "start": "webpack-dev-server" 已经比较成熟了,大部分公司的选择
  3. "server": "node server.js" Node手写

8.2devServer(开发服务器)

webpack-dev-server 为你提供了一个基本的 web server,并且具有 live reloading(实时重新加载) 功能。设置如下:

npm install --save-dev webpack-dev-server

contentBase 修改配置文件,告知 dev server,从什么位置查找文件

devServer: {
    contentBase: './dist',
    open: true,
    port: 8080
},

8.3 webpack-dev-middleware

webpack-dev-middleware 是一个封装器(wrapper),它可以把 webpack 处理过的文件发送到一个 server。

下面是一个 webpack-dev-middleware 配合 express server 的示例。 首先,安装 express 和 webpack-dev-middleware

npm install --save-dev express webpack-dev-middleware

现在,我们需要调整 webpack 配置文件,以确保 middleware(中间件) 功能能够正确启用:

 output: {
+    publicPath: '/',
   },
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');

const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

// 告知 express 使用 webpack-dev-middleware,
// 以及将 webpack.config.js 配置文件作为基础配置。
app.use(
  webpackDevMiddleware(compiler, {
    publicPath: config.output.publicPath,
  })
);

// 将文件 serve 到 port 3000。
app.listen(3000, function () {
  console.log('Example app listening on port 3000!\n');
});

9. HotModuleReplacementPlugin 热模块

模块热替换(HMR - hot module replacement)功能会在应用程序运行过程中,替换、添加或删除 模块,而无需重新加载整个页面。主要是通过以下几种方式,来显著加快开发速度:

  • 保留在完全重新加载页面期间丢失的应用程序状态。
  • 只更新变更内容,以节省宝贵的开发时间。
  • 在源代码中 CSS/JS 产生修改时,会立刻在浏览器中进行更新,这几乎相当于在浏览器 devtools 直接更改样式

9.1 简单使用

hot devServer中开启热模块

hotOnly 即使热更新调用失败也不刷新页面

const webpack = require('webpack');
    module.export = {
        devServer: {
        contentBase: './dist',
        open: true,
        port: 8080,
        hot: true,
        hotOnly: true
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin()
    ],
}

自定义模块更新

accept 

接受(accept)给定 依赖模块(dependencies) 的更新,并触发一个 回调函数 来响应更新,除此之外,你可以附加一个可选的 error 处理程序

module.hot.accept(
  dependencies, // 可以是一个字符串或字符串数组
  callback // 用于在模块更新后触发的函数
  errorHandler // (err, {moduleId, dependencyId}) => {}
);

例子

image.png

10. 使用Babel处理ES6语法(上)

Babel官网

处理日常项目的ES6

10.1 安装

  1. npm install --save-dev babel-loader @babel/core //打通webpack与babel
  2. npm install @babel/preset-env --save-dev 此工具能够处理ES6语法
  3. npm install --save @babel/polyfill 翻译所有ES6语法

10.2 使用

webpack.config.js

rules: [{ 
    test: /\.js$/, 
    exclude: /node_modules/, 
    loader: 'babel-loader',
}]

.babelrc文件为 babel-loader的配置文件

chrome: "67" 版本大于67的不处理

useBuiltIn: 'usage' 只处理项目文件中用到的es6语法,减少打包体积。 此时不需要用到polyfill,但是polyfill仍需要安装

image.png

{
    presets: [['@babel/preset-env', {
        targets: {
             chrome: "67", 
         },
        useBuiltIns: 'usage'
    }]]
}

polyfill使用: import "@babel/polyfill"; 文件内引入即可

11 使用Babel处理ES6语法(下)

image.png babel-plugin-transform-runtime

11.1安装

  1. npm install --save-dev @babel/plugin-transform-runtime
  2. npm install --save @babel/runtime webpack.config.js
rules: [{ 
    test: /\.js$/, 
    exclude: /node_modules/, 
    loader: 'babel-loader',
}]

.babelrc文件

{
	"plugins": [["@babel/plugin-transform-runtime", {
            "corejs": 2,
            "helpers": true,
            "regenerator": true,
            "useESModules": false
	}]]
}