博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Webpack4 不深不浅的实践教程
阅读量:6613 次
发布时间:2019-06-24

本文共 9294 字,大约阅读时间需要 30 分钟。

Webpack Legato

本文偏入门&实践,从零开始配置 Webpack; 实际项目开发,零配置是不存在的。

? 安装&快速开始

快速初始化配置文件 package.json

// npm i yarn -gyarn init -y// yarn init --yes// yarn init --yes=true // 即全部选项默认为 yes

接下来将 webpack 添加到 package.json => devDependencies

yarn add webpack -D

安装成功后,创建目录 src/index.js 并添加如下内容 (默认入口为 src)

document.write("Hello webpack4!");

命令行输入:

webpack --mode=development

成功后显示,打开 dist 文件夹会看到 main.js (默认输出到 dist)

Hash: 771a2645c2d430fa3bb4Version: webpack 4.5.0Time: 128msBuilt at: 2020-4-10 03:14:23  Asset      Size  Chunks             Chunk Namesmain.js  2.81 KiB    main  [emitted]  mainEntrypoint main = main.js[./index.js] 34 bytes {main} [built]
--mode 模式 (必选,不然会有
WARNING),是
webpack4 新增的参数选项,默认是
production
  • --mode production 生产环境

    • 提供 uglifyjs-webpack-plugin 代码压缩
    • 不需要定义 new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }) 默认 production
    • 默认开启 NoEmitOnErrorsPlugin -> optimization.noEmitOnErrors, 编译出错时跳过输出,以确保输出资源不包含错误
    • 默认开启 ModuleConcatenationPlugin -> optimization.concatenateModules, webpack3 添加的作用域提升(Scope Hoisting)
  • --mode development 开发环境

    • 使用 eval 构建 module, 提升增量构建速度
    • 不需要定义 new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }) 默认 development
    • 默认开启 NamedModulesPlugin -> optimization.namedModules 使用模块热替换(HMR)时会显示模块的相对路径

接下来创建 dist/index.html 并引入 main.js, 浏览器中打开看内容。

  
webpack-simple

再创建一个文件 src/content.js, 在 src/index.js 中引入该模块

// content.jsmodule.exports = 'Looooooooooooooong content!';
// index.jsdocument.write(`Hello webpack4!${require('./content.js')}`);

再次执行 webpack --mode=development 完了打开 index.html

// 内容Hello webpack4!Looooooooooooooong content!

? 快速出土 webpack.config.js

安装 webpack-cli 来初始化配置

yarn add webpack-cli -D
webpack-cli init1. Will your application have multiple bundles? No // 单入口 string, 多页面 object2. Which module will be the first to enter the application? [example: './src/index'] ./src/index // 程序入口3. What is the location of "app"? [example: "./src/app"] './src/index' // 程序主文件4. Which folder will your generated bundles be in? [default: dist]: // 输出目录,默认 dist5. Are you going to use this in production? No // (Yes 第9步默认'config', No 则为 'prod')6. Will you be using ES2015? Yes // 会添加 ES6 => ES5 的配置7. Will you use one of the below CSS solutions? CSS // 选一种样式语言,会生成对应的 loader 配置8. If you want to bundle your CSS files, what will you name the bundle? (press enter to skip) // 回车跳过9. Name your 'webpack.[name].js?' [default: 'config']: // webpack.config.jsCongratulations! Your new webpack configuration file has been created!

配置生成OK,如下

// webpack.config.jsconst webpack = require('webpack');const path = require('path');const UglifyJSPlugin = require('uglifyjs-webpack-plugin');module.exports = {  entry: './src/index.js',  output: {    filename: '[name].bundle.js',    path: path.resolve(__dirname, 'dist')  },  module: {    rules: [      {        test: /\.js$/,        exclude: /node_modules/,        loader: 'babel-loader',        options: {          presets: ['env']        }      },      {        test: /\.css$/,        use: [          { loader: 'style-loader', options: { sourceMap: true } },          { loader: 'css-loader' }        ]      }    ]  },  plugins: [new UglifyJSPlugin()]  // 这款插件用于压缩 JS 代码,减少资源体积大小};

再度执行编译一切OK, 打开 index.html 查看内容

webpack --mode=developmentHash: c30d4f489db4d568ee0bVersion: webpack 4.5.0Time: 1308msBuilt at: 2020-4-11 04:14:23Asset      Size  Chunks             Chunk Namesapp.38de904fed135db4bf0a.js  1.17 KiB     app  [emitted]  appEntrypoint app = app.38de904fed135db4bf0a.js[./src/content.js] 62 bytes {app} [built][./src/index.js] 80 bytes {app} [built]

接下来就是在这份配置上,做一些实践。

? 使用 html-webpack-plugin 创建 html 文件

  • 该插件简化了创建 HTML 文件的创建,服务于 webpack bundle。
  • 解决的问题:每次编译完成后不用再去手动修改 index.html, 它会与 JS 生成在同一目录 dist 并引入 app.38de904fed135db4bf0a.js
yarn add html-webpack-plugin -D

安装完成后,在 webpack.config.js 下配置

// webpack.config.js+ const HtmlWebpackPlugin = require('html-webpack-plugin');plugins: [  new UglifyJSPlugin(),+ new HtmlWebpackPlugin({    title: 'webpack-cli'  }),]

重新执行 webpack --mode=development, dist 目录就会多个 index.html 并引入了 main.bundle.js.

⚛️ Webpack4 配置 React 开发环境

上面配置中的 module.rules 的应用

babel-loader 将 ES6* 代码转化为 ES5 代码

Babel 默认只转换新的 JavaScript 句法 (syntax), 而不转换新的 API, 比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转码。

举例来说,ES6 在 Array 对象上新增了 Array.from 方法。Babel 就不会转码这个方法。如果想让这个方法运行,必须使用 babel-polyfill,为当前环境提供一个垫片。—— 摘自

yarn add react react-dom babel-preset-react
babel-preset-react 用于解析
react 的语法;

babel-preset-env 初始化配置时已经安装。它的前身是 babel-preset-es2015/es2016/es2017 以后要用新特性这个包就可以搞定一切。

安装完成,修改 src/index.js 的内容为

import React from 'react';import { render } from 'react-dom';render(

Hello world!

, document.querySelector('#root'));

webpack.config.js module.rules babel-loader 配置 presets 删掉。

在项目根目录新建 .babelrc 文件,内容如下

// .babelrc{    "presets": [        "env",        "react"    ]}
// webpack.config.jsplugins: [  new HtmlWebpackPlugin({+   template: './index.html' // 添加模版文件  }),]
// index.html      
Webpack4-react16

再次执行 webpack --mode=development, ok!

? 实时刷新页面

yarn add webpack-dev-server -D

打开 package.json 添加构建脚本

  • --open 自动打开浏览器并定向至 http://localhost:8080/
"scripts": {    "dev": "webpack-dev-server --mode=development --open --hot"    "//": "webpack-dev-server --mode=development --host 0.0.0.0"    "//": "使用本机 IP 访问项目 [Your IP]:8080 => 192.168.0.111:8080"},

执行 yarn dev, 自动刷新完成。

? 模块热替换

即在不重载页面的情况下,实时替换更新修改的模块。提高开发效率。
本文使用 React, 所以用

yarn add react-hot-loader -D

项目根目录下新建文件 .babelrc, 添加内容:

{+  "plugins": ["react-hot-loader/babel"]}

src 目录下添加文件 App.js

// src/App.jsimport React from 'react';import { hot } from 'react-hot-loader';const App = () => 
Hello World!
;export default hot(module)(App)

应用入口引入 App.js

// src/index.jsimport React from 'react';import { render } from 'react-dom';import App from './App';render(
, document.querySelector('#root'));

重新执行 yarn dev, 修改下 App.js 的代码,注意看浏览器与 console.

[HMR]  - ./src/App.jslog.js:24 [HMR] App is up to date.

如果 hot(module)(App)render 一个文件则会收到警告

? Webpack4 加载 CSS

在 4.x 版本之前,用的是
extract-text-webpack-plugin,不过 webpack@4.3.0 不支持使用。

yarn add mini-css-extract-plugin -D
// module.rules{  test: /\.css$/,  use: [    MiniCssExtractPlugin.loader,    {      loader: 'css-loader',      options: {              }    }  ]}plugins: [  new MiniCssExtractPlugin({    filename: "[name].[contenthash].css",    chunkFilename: "[id].[contenthash].css"  })],

? 按需加载 React 组件

yarn add react-loadableyarn add babel-preset-stage-2 -D // for 动态 import() 语法
import Loadable from 'react-loadable';const Loading = () => 'Loading...';const Home = Loadable({ loader: () => import('./Home'), loading: Loading });

效果如图

按需加载

按需加载OK,不过发现个问题,这个 Header 组件被多处调用,样式&JS都存在多次加载。

样式JS重复加载

接下来要做的就是把共用的代码提取出来。

? Webpack4 提取公共 CSS&JS

配置如下

// webpack.config.jsoptimization: {  splitChunks: {    cacheGroups: {      commons: {        name: 'commons',        priority: 10,        chunks: 'initial'      },      styles: {        name: 'styles',        test: /\.css$/,        chunks: 'all',        minChunks: 2,        enforce: true      }    }  }}

提取共同CSS

css header 被单独提取到 styles.css

? 分离第三方库

entry: {  app: './src/index.js',+ ramda: ['ramda'],}new HtmlWebpackPlugin({  template: './index.html',+ chunks: ['app', 'commons', 'ramda']})2.e9dc7e430f6a31c868b2.css   45 bytes        2  [emitted]                   app.bundle.js    9.6 KiB      app  [emitted]  app      0.decbf5b19337a4ce4aac.css   61 bytes        0  [emitted]                     0.bundle.js   4.01 KiB        0  [emitted]+                ramda.bundle.js   7.99 KiB    ramda  [emitted]  ramda                      index.html  393 bytes           [emitted]

?

yarn add antdyarn add less less-loader babel-plugin-import -D
// .babelrc 添加{  "plugins": [    [      "import",      {        "style": true,        "libraryName": "antd"      }    ]  ]}
// webpack.config.js module.rules 添加{  test: /\.less$/,  use: [    MiniCssExtractPlugin.loader,    'css-loader',    {      loader: 'less-loader',      options: {        sourceMap: true,        javascriptEnabled: true,        modifyVars: {          'primary-color': '#531dab'        }      }    }  ]}

? autoprefixer 处理浏览器前缀

display: -webkit-box;display: -ms-flexbox;display: flex;
yarn add autoprefixer postcss-loader -D

项目根目录新建 postcss.config.js

// postcss.config.jsmodule.exports = {  plugins: [    require('autoprefixer')({      'browsers': ['> 1%', 'last 2 versions']    })  ]};
// webpack.config.js module.rules{  test: /\.css$/,  use: [    MiniCssExtractPlugin.loader,    'css-loader',+   'postcss-loader'  ]}

? 一些报错 & 解决办法

Uncaught Error: [HMR] Hot Module Replacement is disabled.

运行
webpack-dev-server --mode=development 报错。

webpack.config.js devSever hot: true, inline: true 删掉,

添加 webpack-dev-server --mode=development --hot --inline

或者

plugins: [+    new webpack.HotModuleReplacementPlugin(),]

ERROR in 0.js from UglifyJs TypeError: Cannot read property 'sections' of null

TypeError: Cannot read property 'sections' of null ? Remove `new UglifyJsPlugin` from plugins partschema id ignored LoaderOptionsPlugin              ? Remove `new LoaderOptionsPlugin` plugin from configschema id ignored SourceMapDevToolPlugin           ? Remove `devtool` config

ERROR in chunk app [entry] [name].[chunkhash].js

? 参考资料

挤时间敲了几天,教程终于告一段落!后续还会继续完善其他的配置(HappyPack, DllReferencePlugin...)实践;
本文如有错误,欢迎指正,非常感谢。

转载地址:http://tqeso.baihongyu.com/

你可能感兴趣的文章
政府和社会资合作(ppp)概述
查看>>
p6spy介绍
查看>>
记一次mysql中浮点类型字段引起的问题
查看>>
笔记本电脑同时连接无线网络(互联网)和有线网络(内网)的方法
查看>>
eclipse离线插件
查看>>
BOM导致的Build failed in Jenkins with error MSB4025
查看>>
渣打迷你编程马拉松(Mini Code Marathon)小记
查看>>
mac 下添加mysql开机启动
查看>>
末日生存者的信条
查看>>
jquery mobile 定时器代码
查看>>
牛人整理的Django资源大全(转载)
查看>>
Android4.0 WiFi 源码解读
查看>>
反序列化坑
查看>>
dubbo源码解读系列之一dubbo项目组成
查看>>
linux中seq命令用法
查看>>
arnold resouces
查看>>
凭兴趣求职80%会失败,为什么
查看>>
URI的常用使用场景
查看>>
详解网络流量监控
查看>>
Ubuntu 修改 IP/DNS
查看>>