webpack4笔记

安装

// 先初始化项目,创建package用于记录依赖
npm init

// 安装webpack和webpack-cli,-D表示 -dev,开发环境用的包,使用webpack4需要额外安装webpack-cli
npm i webpack@4 webpack-cli -D

五大核心概念

entry:打包入口,支持多入口打包
output:输出,可以配置输入路径,文件名等
loader:webpack只理解javascript语法,loader可以把其他类型的文件如css、less、sass、image、vue等转成js代码。
plugin:负责处理打包优化级相关的事,如设置环境变量、代码压缩等
mode:webpack4特有概念,指开发模式,默认production生产模式,可以设置为development开发模式,不同模式会自动开启一些内置好的plugin。

const { resolve } = require('path')

module.exports = {
  mode: 'development', // 默认production,开发环境请使用development
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    // 这个参数要求绝对路径,因此需要使用node的path模块帮助生成
    // __dirname是内置变量指向当前js文件的目录绝对路径
    path: resolve(__dirname, 'dist'),

  },
  // loader配置
  module: {
    rules: []
  },
  // plugin配置
  plugins: []
}

指定配置文件

默认配置文件名 webpack.config.js
也可以执行命令的时候指定自定义配置文件:webpack --config webpack.config.dev.js
可以在package.js中配置scripts脚本:

"scripts": {
  "webpack --config webpack.config.dev.js"
}

js相关

js压缩:

webpack4已经内置了UglifyJsPlugin,只要mode设置成production就可以做压缩。

js兼容性处理:

npm install -D babel-loader @babel/core @babel/preset-env

webpack 4.x || 5.x | babel-loader 8.x | babel 7.x

@babel/core:核心解析库
babel-loader:webpack需要用的loader
@babel/preset-env:loader的预设配置,默认支持基本的语法转换如const,promise这种不支持,需要额外添加配置指定兼容版本

      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          presets: [
            [
              '@babel/preset-env',
              {
                useBuiltIns: 'usage', // 按需加载兼容性选项
                corejs: {
                  version: 3,
                },
                // 指定兼容最低浏览器版本
                targets: {
                  chrome: '60',
                  firefox: '60',
                  ie: '9',
                  safari: '10',
                  edge: '17',
                },
              },
            ],
          ],
        },
      },

动态加载的语法支持:
使用import()来实现动态加载的时候会报如下错误



貌似babel7还不太完善,这里额外下了个core-js包,问题被解决
npm i -D core-js


css相关

css:
npm i -D style-loader@2 css-loader@5

webpack4不要用最新版本,使用file-loader打包图标库报错


// loader配置
  module: {
    rules: [
      { // 处理css
        test: /\.css$/,
        // use中配置的loader是倒叙执行的
        use: [
          'style-loader', // 创建style标签,将js中的css模块插入到页面上
          'css-loader', // 将css文件转换成js模块
        ]
      }
    ]
  },

less:
npm i less-loader@7 less -D

注意:less-loader8.0以后就不支持webpack4了


{
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          'less-loader'
        ]
      }

css兼容性处理:

npm i -D postcss-loader@4 postcss@8 postcss-preset-env@7

注意postcss-loader从版本5.0以后只支持webpack5

postcss是核心解析api
postcss-loader是webpack需要用的loader
postcss-preset-env是postcss-loader支持的插件,可以配置最低要求浏览器兼容版本,这里是通过package.json上配置browserlist指定具体版本
postcss-loader必须写在css-loader之前,其他样式loader如less-loader后面:

      {
        test: /\.less$/,
        use: [
          // 'style-loader',
          MiniCssExtractPlugin.loader, // 替代style-loader,提取css文件为单独文件
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  'postcss-preset-env'
                ]
              }
            }
          },
          'less-loader'
        ]
      },

package.json追加配置:

  "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  }

同时需要在webpack.config.js指定当前nodejs环境变量,postcss-preset-env会去取当前执行环境,默认production。

process.env.NODE_ENV = "development"

css提取:

npm i -D mini-css-extract-plugin@1
npm官网

安装的时候注意版本,2.0以后就不支持webpack4了。


css-loader会把引入的css文件转为js和js编码打包在一起,如果希望打包后css单独提取到外部文件并用link标签引入,需要安装插件mini-css-extract-plugin,同时用这个插件自带的loader替代style-loader。

const MiniCssExtractPlugin = require('mini-css-extract-plugin')

//...

module: {
  rules: [
    {
        test: /\.less$/,
        use: [
          // 'style-loader',
          MiniCssExtractPlugin.loader, // 替代style-loader,提取css文件为单独文件
          'css-loader',
          'less-loader'
        ]
      },
      { // 处理css
        test: /\.css$/,
        // use中配置的loader是倒叙执行的
        use: [
          // 'style-loader', // 创建style标签,将js中的css模块插入到页面上
          MiniCssExtractPlugin.loader, // 替代style-loader,提取css文件为单独文件
          'css-loader', // 将css文件转换成js模块
        ]
      }
  ]
},
plugins: [
  new MiniCssExtractPlugin({
    filename: 'css/[hash:8].css'
  })
]

这里有时候会遇到这样的问题:
css提取到指定目录后,样式中图片路径会加载不到的问题:
比如url-loader处理后图片加载地址为assets/img/xxx.png,如果MiniCssExtractPlugin.loader配置了publicPath为css,最终图片地址就会变成css/assets/img/xxx.png导致找不到图片,因为assets并不在css目录下,而是在根目录下。通过查看官网例子,得到如下配置方式:

// loader...
module: {
   rules: [
     {
       loader: MiniCssExtractPlugin.loader,
       options: {
        publicPath: '../',
       },
     },
   ]
}


// plugin...
plugins: [
 new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash:8].css',
    }),
]

这样可以做到css文件提取到指定目录,同时样式中图片地址不会拼接错误

css压缩:

npm i -D optimize-css-assets-webpack-plugin@6

optimize-css-assets-webpack-plugin@4.0.0 version and above supports webpack v4.
webpack4使用optimize-css-assets-webpack-plugin4.0.0及以上的版本
顺带记一下webpack5要使用css-minimizer-webpack-plugin

本例使用的是optimize-css-assets-webpack-plugin@6,需要postcss8.0及以上支持

const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')

//...

plugins: [
    new OptimizeCssAssetsWebpackPlugin()
  ]

image

npm i -D url-loader@4 file-loader@6 html-loader@0

webpack4使用老版本html-loader 0.5.5,
新版本需要查看官网html-loader

url-loader依赖file-loader,所以2个都需要安装
url-loader可以处理css中的image
html-loader负责处理html中的image标签,把image标签中的图片转成js模块供url-loader处理,使用html-loader要注意配置url-loader的esModule:false

      {
        test: /\.(jpg|jpeg|png|gif)$/,
        // url-loader依赖file-loader,所以需要安装url-loader和file-loader
        use: 'url-loader',
        options: {
          // 小于8kb就会base64处理,优点是减少请求数,减轻服务端压力,
          // 缺点是文件体积会变大,通常12kb以内可以考虑配置
          limit: 8 * 1024,
          // url-loader默认使用es6模块解析js,但是html-loader解析出来的是commonjs模块,
          // 需要如下配置才能正常加载image标签图片资源
          esModule: false,
          outputPath: "img" // 打包到img目录下
        }
      },
      {
        test: /\.html$/,
        // html-loader负责处理image标签中的图片路径,负责引入图片让url-loader加载
        use: 'html-loader'
      }

html相关

html 模板copy:
npm i -D html-webpack-plugin@4
作用:创建html文件,自动引入js/css

版本问题:



报错原因是版本不兼容,最新的html插件已经升级到5,而使用的webpack版本是4
需要指定版本安装html插件:npm i -D html-webpack-plugin@4

const HtmlWebpackPlugin = require('html-webpack-plugin')

//...

// plugin配置
  plugins: [
    new HtmlWebpackPlugin({
      // 默认只会创建空html,template用于复制自定义html,在基础上插入css和js
      // 可以创建“app”标签,引入cdn库等
      template: './src/index.html'
    })
  ]

html压缩:

需要在HtmlWebpackPlugin中加2个配置项,用于移除空格/空行、移除注释

  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true, // 移除空格
        removeComments: true, // 移除注释
      }
    })
  ]

其他资源打包

字体图标:字体图标是在css中被引入的,需要使用url-loader才能正确解析出地址,可以使用url-loader提取。

  { // 处理字体图标,只会在样式文件中引入,所以使用url-loader提取
    test: /\.(eot|svg|ttf|woff|woff2)/,
    loader: 'url-loader',
    options: {
      name: '[name].[contenthash:8].[ext]',
      limit: 8 * 1024, // 这个选项需要配置,默认不限制文件大小
      outputPath: 'assets/font',
    },
  },

可以直接入口js引入iconfont.css

import './font/iconfont.css'

根据iconfont.css内容copy对应的字体库文件,整个字体图标目录都copy过来也可以,demo_index.html还可以查看图标样式。

image.png

其他文件都可以使用file-loader统一打包到配置的目录下。

{ // 其他文件,没有在样式引入的可以使用file-loader提取到指定目录下
    exclude: /\.(html|css|js|less|jpg|jpeg|png|gif|eot|svg|ttf|woff|woff2)/,
    loader: 'file-loader',
    options: {
      name: '[name].[contenthash:8].[ext]',
      outputPath: 'assets',
    },
  },

devServer

npm i -D webpack-dev-server@4
注意使用的版本,这里安装的是4.0以后的版本。需要:node >= v12.13.0、webpack >= v4.37.0,webpack-cli >= v4.7.0
webpack-dev-server文档

v3和v4的差异请参考官方文档webpack-dev-server迁移

devServer打包好的内容会存在内存中,并不会在打包目录中。

//...

 devServer: {
    // 项目构建后目录
    static: {
      directory: resolve(__dirname, 'public'),
    },
    // gzip压缩
    compress: true,
    port: 3000,
    // 自动打开浏览器
    open: true,
  },

优化项

模块热替换:

模块热替换(HMR):只改了一处js或者css文件,只重新打包加载这一部分,不要更新整个项目所有模块。
需要处理的文件:

  1. html:默认不支持,需要刷新整个页面,单页面通常不会修改入口页面,如果使用vue-loader解析组件,会自带hmr功能
  2. css:style-loader已经支持,所以开发环境使用style-loader,生产环境才提取css
process.env.NODE_ENV = 'development';
const isProductionMode = process.env.NODE_ENV === 'production';

//...

[
isProductionMode ? MiniCssExtractPlugin.loader : 'style-loader',
  'css-loader', 
]
  1. js:devserver默认会开启hot选项,但是会刷新所有模块,入口js无法控制,必然会导致全模块刷新,其他js可以通过在入口加一段代码控制,达到hmr功能。
if (module.hot) {
  module.hot.accept(['./a.js', './b.js'], (name) => {
    console.log(`${name} 被更新`);
  });
}

这意味着我们需要维护所有js文件的列表...
好在大多数情况下,我们使用的组件loader自带了hmr功能,如vue-loader、react Hot Loader,因此这个配置基本可以省略。

source-map:

source-map是一种源代码映射技术,可以帮助开发人员快速定位代码错误。

[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map

//...
devServer:{},
devtool: 'source-map' // 增加源码映射构建

打包方式和调试体验:

  1. inline-和eval-前缀的source-map会把sourcemap代码构建到bundle.js中。
    inline-在bundle中有单独的一块区域存放sourcemap代码;而eval-会在每个依赖文件的eval函数中追加sourcemap代码。排错的体验基本一样。
  2. 除了inline-和eval-前缀的source-map,其他的选项都会在外部生成source-map代码。
  3. hidden-不会让我们看到源代码,只能看构建后bundle的代码。比较适合生产环境定位代码,需要开发人员对源代码熟悉。
  4. nosources-也不会让我们看到源代码。
  5. cheap-和cheap-module-定位的粒度为行,不会具体到哪一句代码。
  6. 什么前缀都不加也是在外部构建映射代码,调试体验自然是最好的。

调试体验:
source-map > cheap- ...

打包速度:
eval > inline > cheap ...
eval-cheap-source-map是最快的

常规配置:

开发环境通常使用eval-source-map,react和vue脚手架的默认配置也是这个
如果希望速度更快,可以考虑eval-cheap-module-source-map

生产环境需要考虑2个问题:

  1. 不能使用内联,会使bundle体积变大,因此不能考虑eval-和inline-
  2. 是否要线上调试代码,如果需要,可以考虑source-map,或者cheap-module-source-map能打包快一些。如果不需要调试,个人觉得就不要配置devtool了,不然会多打个map文件。
    更详细说明可以查看webpack-devtool官方文档

oneOf:

优化loader处理效率:对于那些只会被一种loader处理的文件,可以放到oneOf选项内,避免每次都要被所有loader检查一遍。

const oneOfLoaders = [
  {
    test: /\.js$/,
    exclude: /node_modules/,
    loader: 'babel-loader',
    options: {}
  },
  {
    {
    test: /\.less$/,
    use: [
      ...commonCssLoaders,
      'less-loader',
    ],
  },
  { // 处理css
    test: /\.css$/,
    use: [
      ...commonCssLoaders,
    ],
  },
  }
]

//...

module: {
    rules: [
      {
        test: /\.xxx$/,
        enforce: true, // 如果oneOf内部包含了对此类型文件处理,需要加上此项保证先被命中
        loader: 'xxx-loader'
      },
      {
        oneOf: [...oneOfLoaders],
      },
    ],
  },

缓存:

缓存一般用于生产环境,主要包括2方面:

  1. babel-loader打包缓存配置:babel-loader会在本地默认一个目录下缓存打包的结果,下次打包的时候会优先读取缓存。更多详细配置可以查看webpack babel-loader文档
{
  test: /\.js$/,
   exclude: /node_modules/,
   loader: 'babel-loader',
   options: {
    cacheDirectory: true, // 开启构建缓存
    presets: [
      '@babel/preset-env'
    ]
   }
}
  1. 静态资源缓存:这里主要指通过强制缓存控制js、css、img、字体图标等静态资源缓存,让用户访问页面变得快速。注意html文件不要缓存,静态资源打包输出的文件名要带上contenthash值,这样需要更新文件的时候浏览器就会去下载新的文件而不是用缓存。
    可以参考:关于浏览器缓存nginx配置代理缓存

关于hash的配置:
webpack中,hash有3种:hash、chunkhash、contenthash。
hash:每次构建都会生成一个hash,所有文件共享。这显然不是我们想要的。
chunkhash:属于同一个chunk的文件共享一个chunkhash。就比如一个入口下与入口文件有依赖关系的子文件都属于一个chunk,例如index.js中引入了css文件,那么css文件和index属于一个chunk,即使css后来用插件被提取出去了。
contenthash:这个hash是根据最终输出的文件内容生成的。contenthash可以用于缓存和更新。

tree shaking:

通常我们引入一个js文件,不见得所有的函数和方法都会被引用,有的可能是废弃的代码,tree shaking的作用就是不打包未被引用的方法或对象。

tree shaking的使用很简单:

  1. 使用import 导入,即es6的模块化语法
  2. mode设置为production
    webpack会自动进行tree shaking。

代码分割(code split):

如果我们的项目由单页面发展为多页面,就意味着需要多个入口js(html可以共用一个,作为基础模板),比如用户入口,商家入口,管理员入口等。
这时候会遇到重复打包的问题,例如jquery,会被打包进了2个chunk中。

webpack4以后提供了SplitChunksPlugin帮我们完成了这一需求,主要从以下几个角度考虑分割chunk

  1. 首先node_modules目录中的代码会被直接提取出去,这项功能单页面也适用。
  2. 引入的模块体积大于限定(默认20k)会被分割成单独chunk
  3. 按需加载,并发请求过多会被提炼成单独chunk
  4. 页面初始化,并发请求过多会被提炼单独chunk

常规操作:

// 这样一定会把引用的node_modules中的库抽离到单独的chunk中,
// 其他根据判断规则自动决定是否再抽离chunk
optimization: {
    splitChunks: {
      chunks: 'all',
    },
  },

如果你想指定自己的模块被提炼出单独chunk,无视任何条件,可以使用如下的方式:

import(/* webpackChunkName: 'c' */'./c').then(c => {
  console.log(c.paipai('fang'));
})

懒加载和预加载:

默认代码分割后,js是并行加载的,页面在创建dom的时候,会被不必要的js模块加载造成延迟创建,这会导致体验问题。
懒加载就是开始不加载js代码,用指定的交互行为控制用时才加载。如果加载文件体积太大会可能会出现体验问题。
预加载会等到浏览器空闲的时候再加载,原理是link标签的preload属性控制。空闲具体是指预加载不会打扰dom加载和window.onload事件。
配置过后可以查看页面有没有类似的标签
<link as=script href=/js/app.69189fdd.js rel=preload>
<link as=style href=/css/app.f60416c7.css rel=preload>
原理和兼容性介绍

// 懒加载
btn.onclick = ()=> {
  import(/* webpackChunkName: 'c' */'./c').then(c => {
    console.log(c.paipai('fang'));
  })
}

// 预加载
import(/* webpackChunkName: 'c', webpackPrefetch: true */'./c').then(c => {
  console.log(c.paipai('fang'));
})

https://webpack.docschina.org/guides/lazy-loading/
查看文档发现vue的懒加载只需要import()的方式。可以参看dynamic-imports-in-vue-js-for-better-performance

使用cdn:

有些第三方库,如vue,jquery等,可以抽离出去,使用外网的免费cdn连接加载,这样可以减少打包体积。当然有时候内网部署的话,把这些不会变化的库提炼出来改为link插入也是类似效果,只不过cdn的网络理论上会好一些,但是稳定性不确定,毕竟是外网链接。
建议生产环境使用cdn,开发环境使用打包方式引入。
cdn网站比如:https://www.bootcdn.cn/
其他的可以自己查找

<!-- 在body结尾加上 -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.common.prod.min.js"></script>

// webpack.config.js中
{
  externals: {
    vue: 'Vue'
  }
}

使用dll技术:

dll技术可以告知webpack,打包的时候忽略哪些库。这样打包的时候就不会打包这些库。除此之外,需要事先把这些库抽离出来,配置好映射关系(manifest),再通过插件在打包的时候把这些库通过script引入到html中去。

相比external,dll也是一种很不错的第三方库抽离方案,即可以减少打包体积,提高开发效率,也不受外网环境影响。

具体步骤:

  1. 单独打包指定库:
    先创建一个单独的webpack配置文件,这里命名为webpack.dll.config.js:
const { resolve } = require('path');
/* eslint-disable */
const webpack = require('webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
/* eslint-enable */

module.exports = {
  mode: 'production',
  entry: {
    dll: ['jquery', 'moment'],
  },
  output: {
    filename: '[name].js',
    path: resolve(__dirname, 'dll'),
    library: '[name]_[hash:10]', // 打包库对外暴露的引用命名
  },
  plugins: [
    new CleanWebpackPlugin(),
    // 用于产生manifest文件,用于映射打包文件
    new webpack.DllPlugin({
      name: '[name]_[hash:10]',
      path: resolve(__dirname, 'dll/manifest.json'),
    }),
  ],
};

这里用到了webpack.DllPlugin,主要用来生成manifest.json映射文件
需要抽离的库在entry处配置
执行命令webpack --config webpack.dll.config.js
会在指定dll目录下生成2个文件dll.js和manifest.json

这里发现个问题就是manifest.json只能映射一个文件,所以只能抽离一个包,
entry配置多个入口虽然可以打出多个包,但是manifest只会引最后一个,
这会产生一个体积过大的问题,个人感觉这个方案还是比较适合开发环境

  1. webpack.config.js文件中配置manifest映射关系,这样webpack打包就会根据映射文件不把指定文件打包到bundle中,同时根据映射文件修改库引用名(就是这个[name]_[hash:10])
const webpack = require('webpack');

//...

plugins: [
new webpack.DllReferencePlugin({
  manifest: resolve(__dirname, 'dll/manifest.json'),
}),
]

此时再打包会发现,bundle体积减小很多,重复打包的速度会快很多。但是因为第三方库没有打包进来,就没法引用到,所以还需要把dll.js通过script标签引用到html中。

  1. 使用插件引入dll.js
    需要先下载npm包:
    npm i -D add-asset-html-webpack-plugin

这个包依赖html-webpack-plugin,具体版本要求可以查看官网add-asset-html-webpack-plugin

然后就是配置plugin:

const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');

//...

plugins: [
    // 将dll.js单独打包到指定目录中,并压缩,同时html中引入script标签
    new AddAssetHtmlPlugin({
      filepath: resolve(__dirname, 'dll/dll.js'),
      outputPath: 'js',
    }),
]

辅助小插件

clean-webpack-plugin:
注意关注npm官方文档,目前支持webpack4+,node10+
npm i -D clean-webpack-plugin

const {CleanWebpackPlugin} = require('clean-webpack-plugin')

//...

plugins: [
    new CleanWebpackPlugin()
]

代码规范

npm i -D eslint eslint-webpack-plugin eslint-config-airbnb-base eslint-plugin-import

eslint:核心解析库
eslint-webpack-plugin:取代了eslint-loader,作为webpack的plugin,内置了一些常用配置
eslint-config-airbnb-base:es规范配置库,支持es6+的语法,如果是react体系需要用eslint-config-airbnb替代
eslint-plugin-import:帮助webpack导入代码规范库

eslint-webpack-plugin有些常用配置如屏蔽node_modules这个插件默认配置了,基本零配置直接用就可以,如果使用vscode,建议配置好IDE插件自动格式化,如果还有报红报黄也一目了然,解决好了才允许提交,这样开发人员基本不用操心代码规范问题。

有时候开发测试代码如console想暂时保留,可以先屏蔽eslint检查。
代码中屏蔽eslint检查以下几种方式:

  1. 文件顶部 /* eslint-disable / 整个文件不检查,
    也可以指定规则整个文件不检查/
    eslint-disable no-console */,多个规则空格隔开
  2. // eslint-disable-next-line 单行不检查
  3. 指定范围不检查:/* eslint-disable / 和 / eslint-enable */ 之间的代码都不会检查。
/* eslint-disable */

console.log('aaa')

/* eslint-enable */
  1. 还可以指定特定规则不检查
/* eslint-disable no-console */

alert('lalala')
console.log('aaa')

/* eslint-enable no-console */
  1. 还可以在配置中指定不处理某条规则:
// package.json中
"eslintConfig": {
    "extends": "airbnb-base",
    "rules": {
      "no-console":"off"
    }
  }

webpack.config.js:

const EslintWebpackPlugin = require('eslint-webpack-plugin');

//...

plugins: [
    new EslintWebpackPlugin()
]

package.json追加配置:

//...

"eslintConfig": {
    "eslintConfig": {
      "extends": "airbnb-base",
      "rules": {
        "no-console":"off"
      },
      "parserOptions": {
        "ecmaVersion": 2020
      }
    }
  }

在使用webpack做代码分割的时候,如果用到动态import,默认eslint检查是不通过的,"ecmaVersion": 2020可以解决这个问题~

如果你是vue使用者,还需要安装eslint-plugin-vue,可以对vue文件组件进行的规范检查。

npm i -D eslint-plugin-vue

配合vscode的eslint插件,可以让ide正确的识别vue组件内容和自动格式化。同时eslint配置也可以写到单独的eslintrc.js文件中。

module.exports = {
  extends: [
    'plugin:vue/essential',
    'airbnb-base',

  ],
  rules: {
    'no-console': 'off',
    'no-new': 'off',
    'import/no-unresolved': 'off',
    'import/extensions': 'off',
    'space-before-function-paren': 'off',
    'vue/multi-word-component-names': 'off',
  },
  parserOptions: {
    ecmaVersion: 2020,
  },
};

其他功能

resolve配置:

  1. 别名:
  resolve: { // 配置解析模块规则,比较常用的就是别名,缺点是,ide可能无法正常提示路径
    alias: {
      $css: resolve(__dirname, 'src/css'),
      $assets: resolve(__dirname, 'src/assets'),
      $js: resolve(__dirname, 'src/js'),
    },
  },

如果你用了eslint,打包的时候会检查出错误“import/no-unresolved”,需要配置一下eslint配置文件,这里是直接写在package.json中:
屏蔽掉这条规则,打包的时候不需要eslint检查,如果你vscode安装了eslint插件,也会跟着屏蔽掉这个规则。

  "eslintConfig": {
    "rules": {
      "import/no-unresolved": "off"
    },
  }

还有一种方式是,下载插件:
npm i -D eslint-import-resolver-webpack
然后,配置如下:

  "eslintConfig": {
    "rules": {
      "import/no-unresolved": "off"
    },
    "settings": {
      "import/resolver": {
        "webpack": {
          "config": "./webpack.config.js"
        }
      }
    }
  }

多出来的这些配置主要是帮助插件找到别名配置,可以让eslint正确识别路径,打包不会报错了,
但是ide还是会标红,最终"import/no-unresolved": "off"这条规则还是得加上去,
既然都屏蔽了,eslint-import-resolver-webpack也没有必要用了。

  1. 文件扩展名
  resolve: {
    // 配置可省略的文件后缀名默认是js和json
    extensions: ['.js', '.json', '.less', '.css', '.vue'],
  },

根据自身项目情况,可以追加文件扩展名,这样写代码的时候可以省略文件扩展,当然如果文件同名但是扩展名不同,解析器会优先找js文件,开发中最好不要有同名的情况。

webpack官方文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容