记一次webapck4 配置文件无效的解决历程


Posted in Javascript onSeptember 19, 2018

webpack@4.x的变化

先来说下webpack4和之前版本里一些主要的变化:

1、webpack不再支持node v4,这是因为新的webpack和附属插件使用了es6的语法,v4版本对es6不是很到位,所以,就不伺候了。

2、开始采取约定优于配置的思路,webpack@4.x里把很多选项都设置了默认值,比如入口就是./src,输出目录就是./dist,当然如果你自己去设置,它也不会拦着。所以在用webpack@4.x的时候,我们甚至都可以没有webpack.config.js这个配置文件也能一样打包。

3、拆分了旧版本里的webpack,分成了用来处理逻辑的webpack和提供可执行命令的webpack-cli,这也是有的同学把webpack装成新版本以后会报找不到webpack-cli模块这个错误的原因。

4、添加了mode选项,用来区分编译的环境,提供了development、production和none三个选项,理论上这个选项是强制指定的,其实不指定的话它也是有默认值的,但会给出一个warning,官方这么强烈建议了,就显式的指定一下吧。指定方式有两种,一是在启动命令里:

./node_modules/.bin/webpack --mode production

另外一种就是在配置文件里指定,方式如下:

var config = {
  mode: 'production' // 可选development、production和none
}

5、配置上的变动,类似删除了commonChunksPlugin,用optimization来代替这种。还有loader的用法也和1.15.0不一样了,但这个升级是在之前版本里就有的,不是webpack@4.x带来的。

6、性能优化,提高了打包性能。另外从webpack2起,引入了Tree-shaking机制来提出没有被引用的模块。它的原理是按着引用关系重新建立一个新的依赖树,而没有被引用的模块就不会被打包到最后的代码里。之前的压缩优化方式是先把所有模块都挂到树上,然后通过分析后,删掉没被引用的模块。从字面意思来看,我觉得原来的方式更像在摇树,把没用的摇下来。这两种方式最后压缩完的结果可能类似,但设计思路完全是从两个方向走的。

7、其他。以上这些就是一些比较主要的变化,更详细的升级文档可以参考下官方的说明:https://github.com/webpack/webpack/releases

前言

升级webpack4,一定要去看文档,特别是 更新说明 ,不要自持用过原本webpack就自己开始折腾。折腾到后面,可能就默默流下眼泪了。

webpack4的变化

webpack-cli抽离

webpack-cli被单独拆了出来,使用的时候如果只是全局装了CLI,直接执行的时候是可以的。

webpack --config ./config/webpack.dev.js

如果是写在npm hook里面会发现有点问题:

//package.json
"scripts": {
  "dev": "webpack --config ./config/webpack.dev.js"
 }
//shall
npm run dev

此时就会给提示:

One CLI for webpack must be installed. These are recommended choices, delivered as separate packages:
 - webpack-cli (https://github.com/webpack/webpack-cli)
   The original webpack full-featured CLI.
 - webpack-command (https://github.com/webpack-contrib/webpack-command)
   A lightweight, opinionated webpack CLI.
We will use "npm" to install the CLI via "npm install -D".
Which one do you like to install (webpack-cli/webpack-command):

如果是我没有全局装,我肯定会意识到要选一个,这个坑关键是我全局装了。所以就在那折腾半天。

其实官方文档开头就说明了。

npm install webpack webpack-cli --save-dev

安装完成之后,继续执行发现有warning:

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/

mode规则

配置规则:必须在production 和 development之间选择一种,以便webpack 使用相应模式的内置优化

  1. production支持所有类型的优化已生成最优bundles
  2. development允许注释、提示和eval devtool devtool的差别可以参考这里
  3. production不支持watching、development针对快速增量重建进行了优化
  4. production支持 module concatenating(Scope Hoisting)即作用域提升,可以将模块打包在一个函数里,这样减少了函数声明,文件体积也会减小。 详细参考看这里
  5. process.env.NODE_ENV被设置用来区分环境(仅仅在构建代码而非config里面)
  6. 有一个hidden none mode的模式可以禁用所有内容

用法:

1、配置文件中:

module.exports = {
entry: Entrys,
mode: 'development'
}

2、cli 参数传入

webpack --mode=development

两种方式都是可行的,不过我遇到过一个很坑的问题,困扰自己好几天,最后知道真相的自己眼泪掉下来后面再提这个问题。

零配置快速开始

因为一直被吐槽配置太累,加上parcel给的压力,webpack4也支持零配置打包了。

如果没有配置文件,会默认以./src/index.js作为entry开始打包。

如果配置了webpack.config.js或者指定了--config 的文件路径,则依据对应配置文件开始。

问题表现

在webpack.config.js中配置了entry、mode等相关属性,配置文件如下:

module.export = {
  mode:'production',
  entry:{
    app:'./src/test.js',
    index:'./src/test.js'
  },
  output: {
    path: process.cwd() + '/dist',
    filename: '[name].[hash].js',
    chunkFilename: '[name].[chunkhash].js',
    crossOriginLoading: 'anonymous'
  },
  cache: true,
  devtool: 'cheap-source-map',
  externals: {
    jquery: 'jQuery'
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)?$/,
        include: [
          path.resolve(__dirname, "../src")
        ],
        exclude: [
          'node_modules',
          path.resolve(__dirname, "../node_modules")
        ],
        use: [
          {
            loader: 'babel-loader',
            options:{
              presets:['es2015']
            } 
          }
        ]
      }
    ]
  },
  resolve: {
    modules: [
      'node_modules'
    ],
    extensions: [".js", ".json", ".jsx", ".css"],
  },
  devServer: {
    proxy: { // proxy URLs to backend development server
      '/api': 'http://localhost:3000'
    },
    contentBase: path.resolve(__dirname, "../dist"),
    hot: true,
    open:true
  },
  plugins: [
    new CleanWebpackPlugin(['dist']),
    new HtmlWebpackPlugin({
      title:'test'
    }),
    new webpack.HotModuleReplacementPlugin()
  ]
}

package.json命令配置:

"scripts": {
  "build": "webpack --config webpack.prod.js"
 }
//执行打包
npm run build

发现始终会有上面选择mode类型的提示,这让人不能接受,另外提示没有./src/index.js文件,但是我的配置入口是别的文件,这样让人很莫名

ERROR in Entry module not found: Error: Can't resolve './src' in '/Users/****'

本着跟着提示解决问题的原则,少文件那就建一个呗(后来发现这种思维有时候有用,有时候还真要慎重),问题表现虽然一致,实质可能有所不同。

新建之后是可以运行了但是我们的配置文件好像没起作用,

dist下的打包文件是默认的main.js

而非我们指定的app和index

为了确保进入配置文件,我打了几个log,竟然都有输出,说明进去了,这问题就诡异了。

console.log(path.resolve(__dirname, './src')) //输出正确路径
module.export = {
    //*****//
  }

版本统一

初步猜想是版本问题,确实也有issue上提到过某些版本存在问题,对照着官方demo锁定版本之后问题依然存在。

猜测:应该是配置文件存在错误

配置检查

将官方最基本的配置拉进来拷贝进来试了一下,依然存在问题没能解决。

猜测:本地的环境存在问题,npm,node等版本

查看之后发现版本都是满足的。

运行demo

将demo拉到本地并启动,demo正常打包,说明本地环境是ok的。那么问题就明显了,我的配置文件或者项目搭建有问题,对照着demo的配置项,配置项没有明显问题,这样的话将,配置信息放入到demo中去,修改之后发现起作用,我又重新审视了下我的配置文件,不仅仅局限于配置部分的时候,发现

//我的写法,这样webpack拿到的就是undefined了。
module.export
//别人的demo
module.exports

webpack的兼容处理

webpack会将 webpack --config 传入的文件与本身默认配置进行merge,保证本身打包不出错。为了证明我们的推论,将配置文件只剩下output属性,并加上src/index.js

module.exports = {
  output: {
    path: process.cwd() + '/dist1',
    // 直接的入口模zzz块名
    filename: '[name].js',
    // 非入口模块,也就是不需要打包到一起的,但又可能会用到,
    // 这不就是按需加载的么
    chunkFilename: '[name].[chunkhash].js',
    crossOriginLoading: 'anonymous'
  }
}

执行之后会发现打包到/dist1下面。所以上面写错module.exports的时候,走的完全是默认配置。前面的log打在了module.exports之前执行是正确的。

结尾

当遇到不可思议的问题的时候,建议静下心看一看,不要盲目搜索,另外最可靠的参考就是官方文档和实例,注意对比版本和环境,如果都没问题,那么再去尝试网上的各种解决方法。

这里总结一下给自己一个记录,希望解决思路能帮助其他人。也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
发一个自己用JS写的实用看图工具实现代码
Jul 26 Javascript
改写一个简单的菜单 弹性大小
Dec 02 Javascript
a标签的href和onclick 的事件的区别介绍
Jul 26 Javascript
javascript中数组的多种定义方法和常用函数简介
May 09 Javascript
js中实现多态采用和继承类似的方法
Aug 22 Javascript
javascript中slice(),splice(),split(),substring(),substr()使用方法
Mar 13 Javascript
Js实现自定义右键行为
Mar 26 Javascript
JavaScript实现网页对象拖放功能的方法
Apr 15 Javascript
AngularJS过滤器filter用法实例分析
Nov 04 Javascript
在vue项目中引入高德地图及其UI组件的方法
Sep 04 Javascript
详解nvm管理多版本node踩坑
Jul 26 Javascript
vue 项目中当访问路由不存在的时候默认访问404页面操作
Aug 31 Javascript
解决vue热替换失效的根本原因
Sep 19 #Javascript
三种Webpack打包方式(小结)
Sep 19 #Javascript
Vue.js更改调试地址端口号的实例
Sep 19 #Javascript
vue添加axios,并且指定baseurl的方法
Sep 19 #Javascript
vue中的计算属性实例详解
Sep 19 #Javascript
Vue axios设置访问基础路径方法
Sep 19 #Javascript
json前后端数据交互相关代码
Sep 19 #Javascript
You might like
解决了Ajax、MySQL 和 Zend Framework 的乱码问题
2009/03/03 PHP
php面向对象全攻略 (十七) 自动加载类
2009/09/30 PHP
使用VisualStudio开发php的图文设置方法
2010/08/21 PHP
php实现redis数据库指定库号迁移的方法
2015/01/14 PHP
PHP SPL标准库之数据结构栈(SplStack)介绍
2015/05/12 PHP
必须收藏的php实用代码片段
2016/02/02 PHP
ThinkPHP开发--使用七牛云储存
2017/09/14 PHP
TP5(thinkPHP框架)实现后台清除缓存功能示例
2019/05/29 PHP
laravel 时间格式转时间戳的例子
2019/10/11 PHP
JavaScript 验证浏览器是否支持javascript的方法小结
2009/05/17 Javascript
获得Javascript对象属性个数的示例代码
2013/11/21 Javascript
控制input输入框中提示信息的显示和隐藏的方法
2014/02/12 Javascript
jquery常用操作小结
2014/07/21 Javascript
JavaScript学习笔记之JS事件对象
2015/01/22 Javascript
浅谈如何实现easyui的datebox格式化
2016/06/12 Javascript
jQuery和JavaScript节点插入元素的方法对比
2016/11/18 Javascript
js+canvas实现动态吃豆人效果
2017/03/22 Javascript
JavaScript中闭包的详解
2017/04/01 Javascript
vue2实现移动端上传、预览、压缩图片解决拍照旋转问题
2017/04/13 Javascript
基于Vue实现拖拽效果
2018/04/27 Javascript
详解Vue 多级组件透传新方法provide/inject
2018/05/09 Javascript
Vue编写可显示周和月模式的日历 Vue自定义日历内容的显示
2019/06/26 Javascript
用vue设计一个日历表
2020/12/03 Vue.js
高性能web服务器框架Tornado简单实现restful接口及开发实例
2014/07/16 Python
python腾讯语音合成实现过程解析
2019/08/01 Python
Window10下python3.7 安装与卸载教程图解
2019/09/30 Python
安装PyInstaller失败问题解决
2019/12/14 Python
Python中的 ansible 动态Inventory 脚本
2020/01/19 Python
简单了解python调用其他脚本方法实例
2020/03/26 Python
css3过渡_动力节点Java学院整理
2017/07/11 HTML / CSS
加拿大国民体育购物网站:National Sports
2018/11/04 全球购物
意大利消费电子产品购物网站:SLG Store
2019/12/26 全球购物
工作时间擅自离岗检讨书
2014/10/24 职场文书
2015暑期社会实践通讯稿
2015/07/18 职场文书
Python如何利用正则表达式爬取网页信息及图片
2021/04/17 Python
HTML静态页面获取url参数和UserAgent的实现
2022/08/05 HTML / CSS