Webpack入门到精通 五(常用配置)

Webpack入门到精通 五(常用配置)

为更好的阅读体验请移步掘金

初始化项目

mkdir webpack-config-demo
yarn init -y
yarn add webpack webpack-cli

package.json中添加

"scripts": {
    "build": "webpack"
+ src/index.js
const fn = ()=>{
  var a = 100
  var b = 100
  setTimeout(()=>{
    console.log(a + b)
fn()

运行 yarn build ,就会看见当前打包好的 dist.js 文件



webpack build 支持IE

+ browserslistrc文件
[production]
[modern]
last 1 chrome version
last 1 firefox version
[ssr]
node 12

用babel-loader打包js

babel-loader npm

yarn add -D babel-loader @babel/core @babel/preset-env
+ webpack.config.js
module.exports = {
  mode: "production",
  module: {
    rules: [
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env'],
              ['@babel/preset-react',
                  runtime: 'classic'  //使用经典版
}

用babel-laoder打包jsx

yarn add @babel/preset-react
use: {
  loader: 'babel-loader',
  options: {
    presets: [
      '@babel/preset-env',
      '@babel/preset-react' //新增
}

测试

src/index.js
import JsxDemo from'./jsx-demo.jsx'
console.log(JsxDemo)
+ src/jsx-demo.jsx
const JsxDemo = () => {
  return (
    <div>jsx-demo</div>
export default JsxDemo

yarn build



给webpack配置eslint

eslint-config-react-app 此包包含Create React App使用的可共享 ESLint 配置。 npm link

yarn add -D 
eslint-config-react-app 
@typescript-eslint/eslint-plugin@^4.0.0 
@typescript-eslint/parser@^4.0.0 
babel-eslint@^10.0.0 
eslint@^7.5.0 
eslint-plugin-flowtype@^5.2.0 
eslint-plugin-import@^2.22.0 
eslint-plugin-jsx-a11y@^6.3.1 
eslint-plugin-react@^7.20.3 
eslint-plugin-react-hooks@^4.0.8
+ .eslintrc.js
module.exports = {
  //继承 eslint-config-react-app这个里面包含create react app的eslint配置
  "extends": "react-app",
  rules: {
    // jsx使用 react
    'react/jsx-uses-react': [2],
    // 提示要在 JSX 文件里手动引入 React
    'react/react-in-jsx-scope': [2],
    'no-console': [0]
}

webpack 可以感知到 eslint 的配置,从而在编译的过程中提示报错信息

yarn add eslint-webpack-plugin -D
webpack/config.js
const ESLintPlugin = require('eslint-webpack-plugin');
module.exports = {
  // ...
  plugins: [new ESLintPlugin({
    extensions: ['.js', '.jsx']  //不加就不会去检测.jsx文件了
  })],
  // ...
};

在没加 eslint-webpack-plugin 之前虽然我们发现在编辑器中 eslint 给我们报错了,但是在我们运行 yarn build 的时候他还是可以编译成功的。如下图



下面我们来看看加完之后的情况,这个时候,不仅 eslint 报错了 webpack 构建的时候也会在控制台报错,这样就很好地使用了 eslint



用babel-loader打包TypeScript

yarn add @babel/preset-typescript -D

babel 官网

webpack.config.js
test: /\.[tj]sx?$/,
presets: [['@babel/preset-typescript']]

添加一个 test.tsx ,并且在 index.js 中引入,以下结果编译成功。



让eslint支持TypeScript

eslint 支持 ts ,添加相关的配置。

yarn add eslint-config-airbnb-typescript @types/react -D
.eslintrc.js
 //覆盖之前的配置(检测ts代码)
  overrides: [{
    files: ['*.ts', '*.tsx'],
    parserOptions: {
      project: './tsconfig.json',
    extends: ['airbnb-typescript'],
    rules: {
      '@typescript-eslint/object-curly-spacing': [0],
      'import/prefer-default-export': [0],
      'no-console': [0],
      'import/extensions': [0]
  }]

我们运行 yarn build 发现此时编译还是可以成功的。


webpack.config.js 添加'.ts' '.tsx'
plugins: [new ESLintPlugin({
    extensions: ['.js', '.jsx', '.ts', '.tsx']  //不加就不会去检测.jsx文件了

修改之后的效果



用babel-loader打包tsx

生成 tsconfig.json 文件。

npx tsc --init
 "jsx": "react", // Specify JS
 "strict": false, // 关闭严格模式  
  "noImplicitAny": true,  //没有隐式的any
}

同样我们编写 tsx-demo.tsx 文件在 index.js 中引入进行测试。

CRLF 是什么?

一、LF和CRLF是什么

  • CRLF 是 carriage return line feed 的缩写,中文意思是回车换行。
  • LF 是 line feed 的缩写,中文意思也是换行。
  • 它们都是文本换行的方式。

二、LF和CRLF区别

  • CRLF : "\r\n", windows系统环境下的换行方式
  • LF : "\n", Linux系统环境下的换行方式

让js和ts支持@alias

js 支持
webpack.config.js
const path = require('path')
resolve: {
    alias: {
      '@': path.join(__dirname, './src/')
ts 支持
tsconfig.json 添加
"compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": [
        "src/*"

引入代码测试

让webpack支持scss

sass-loader npm

yarn add sass-loader sass style-loader css-loader -D
module.exports = {
  module: {
    rules: [
        test: /\.s[ac]ss$/i,
        //执行顺序从右到左
        use: [
          // Creates `style` nodes from JS strings
          "style-loader",
          // Translates CSS into CommonJS
          "css-loader",
          // Compiles Sass to CSS
          "sass-loader",
};

scss自动import全局文件

{
    test: /\.s[ac]ss$/i,
    use: [
      // Creates `style` nodes from JS strings
      "style-loader",
      // Translates CSS into CommonJS
      "css-loader",
      // Compiles Sass to CSS
        loader: "sass-loader",
        options: {
          //需要添加的字符串
          additionalData: `
          @import '@/var.scss';
          sassOptions: {
            includePaths: [__dirname]  //基于当前目录

scss分享变量给js

可以让项目中用到的 css 变量用同一份 js scss 共同维护一份变量。

+ scss-export.scss
:export {
  border-color: $body-color;
index.js
import vars from './scss-export.scss';
console.log(vars)



webpack支持less文件

less-loader npm

yarn add less less-loader -D
@import './_var.less';
body{
  color: @color;
webpack.config.js
    test: /\.less$/i,
    use: [
        loader: "style-loader",
        loader: "css-loader",
        options: {
          modules: {
            compileType: 'icss',
        loader: "less-loader",
        options: {
          additionalData: `
                @import './_var.less';
  },

less分享给js

_var.less
@color: pink;
:export{
  color: @color;
index.js
import vars from './_var.less';
console.log(vars)

对比scss 和less

要选的话就选 scss

stylus文件

stylus npm

style.stylus
color = black;
//变量分享给js
:export{
  color: color
yarn add stylus stylus-loader -D
webpack.config.js
    test: /\.styl$/,
    use: [
        loader: "style-loader",
        loader: "css-loader",
        options: {
          modules: {
            compileType: 'icss',
        loader: "stylus-loader",
        options: {
          stylusOptions: {
            import: [path.resolve(__dirname, "src/_var.styl")]
}

webpack config 重构

webpack.config.js
const cssLoaders = (...loaders) => [
  // Creates `style` nodes from JS strings
  "style-loader",
  // Translates CSS into CommonJS
    loader: 'css-loader',
    options: {
      modules: {
        compileType: 'icss',
  ...loaders

生产页面单独提取css文件

mini-css-extract-plugin webpack文档

yarn add mini-css-extract-plugin -D
webpack.config.js
const cssLoaders = (...loaders) => [
  // Creates `style` nodes from JS strings
  mode === 'production' ? MiniCssExtractPlugin.loader : "style-loader",
  // Translates CSS into CommonJS
    loader: 'css-loader',
    options: {
      modules: {
        compileType: 'icss',
  ...loaders
plugins: [
    new ESLintPlugin({
      extensions: ['.js', '.jsx', '.ts', '.tsx']  //不加就不会去检测.jsx文件了
    mode === 'production' && new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css'
].filter(Boolean)

自动生成HTML页面

html-webpack-plugin npm

yarn add html-webpack-plugin -D
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  entry: 'index.js',
  output: {
    filename: '[name].[contenthash].js'
  plugins: [
    new HtmlWebpackPlugin()
}

webpack优化 单独打包runtime

optimization: {
    runtimeChunk: 'single',  //运行时文件单独打包

为什么要单独打包runtime

  • runtime 里面的文件是 webpack 为了运行 main.js 文件所要依赖的文件。
  • 如果不单独打包,如果我们修改了 webpack 的配置之后 mian.js 里面的内容就会发生变化,用户的缓存就会失效,如果单独打包的话当修改完 webpack 的配置之后只,如果我们没有改变 main.js 里面的内容的话,就不会重新打包 main.js 的内容,这样就可以节省宽带,提高用户访问页面的速度。

webpack优化 用splitChunks将node依赖单独打包

在编译的时候要缓存 React 等类库文件。

webpack优化 固定modules

webpack.config.js
optimization: {
moduleIds: 'deterministic',
runtimeChunk: 'single',  //运行时文件单独打包
splitChunks: {
  cacheGroups: {
    vendor: {
      priority: 10,
      minSize: 0, /* 如果不写 0,由于 React 文件尺寸太小,会直接跳过 */
      test: /[\\/]node_modules[\\/]/, // 为了匹配 /node_modules/ 或 \node_modules\
      name: 'vendors', // 文件名
      chunks: 'all',  // all 表示同步加载和异步加载,async 表示异步加载,initial 表示同步加载
      // 这三行的整体意思就是把两种加载方式的来自 node_modules 目录的文件打包为 vendors.xxx.js
      // 其中 vendors 是第三方的意思

之后再运行 yarn build 可以看见引入了三个 js 文件



optimizationmoduleids

webpack 多页面

webpack.config.js
entry: {
    main: './src/index.js',
    admin: './src/admin.js'
plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      chunks: ['main']
    new HtmlWebpackPlugin({
      filename: 'admin.html',
      chunks: ['admin']
]



webpack优化 common插件

如果共有的文件就打包成一个文件,如果两个入口都同时引用了一个文件,

optimization: {
    runtimeChunk: 'single',  //运行时文件单独打包
    splitChunks: {
      cacheGroups: {
        common: {
          priority: 5,
          minSize: 0,
          minChunks: 2, //同一个文件至少被多少个入口引用了
          chunks: 'all',
          name: 'common'
  1. runtime 为了运行 mian.js 所要提供的代码。
  2. node_modules venders 全局的
  3. common 模块间的 admin.js 和 index.js
  4. self 自身的

看这个打包之后页面引入 js 的顺序



无限多页面的实现思路

webpack.config.js
let entry = {}
let outputHtml = []
var pages = fs.readdirSync(path.resolve(__dirname, pagesDir))
pages.forEach((item)=>{
  let name = item.replace('.js', '')
  entry[name] = `${pagesDir}${item}`