当前位置: 首页 > news >正文

webpack4 正确的配置方式

原文转载于 www.rails365.net

原文: A tale of Webpack 4 and how to finally configure it in the right way

基本构建

开始新的项目

mkdir webpack-4-tutorial
cd webpack-4-tutorial

npm init
复制代码

上下会初始化一个项目,接下来添加webpack4.

npm install webpack webpack-cli --save-dev
复制代码

确定装的webpack版本是4.

接下来修改package.json

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack"
 },
复制代码

保存之后,npm run dev会出现一个错误.

Insufficient number of arguments or no entry found.
Alternatively, run 'webpack(-cli) --help' for usage info.

Hash: 4442e3d9b2e071bd19f6
Version: webpack 4.12.0
Time: 62ms
Built at: 2018-06-22 14:44:34

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/

ERROR in Entry module not found: Error: Can't resolve './src' in '~/workspace/webpack-4-tutorial'
复制代码

两个问题,第一个出错的意思是说,没有设置mode,默认会认为是production模式。第二个是说src下没有找到入口模块。

我们来改下,再次打开package.json

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack --mode development"
  },
复制代码

在项目下新建src文件夹,然后src下新建index.js.

console.log(“hello, world”);
复制代码

保存后再次运行npm run dev.

这时候成功打包,发现项目里多了一个dist文件夹. 这是因为webpack4是号称0配置,所以很多东西都给你配置好了,比如默认的入口文件,默认的输出文件。 在webpack中配置环境,基本都是两个配置文件(development, production).在webpack4中,有这两个模式来区分。

"scripts": {
  "dev": "webpack --mode development",
  "build": "webpack --mode production"
}
复制代码

保存后运行npm run build,你会发现main.js文件小了很多。

上面很多东西都是通过默认配置来的,尝试去重写配置,在不使用配置文件的情况下。

"scripts": {
     "dev": "webpack --mode development ./src/index.js --output ./dist/main.js",
   "build": "webpack --mode production ./src/index.js --output ./dist/main.js"
 },

复制代码

编译转换你的代码

es6就是未来,可是现在的浏览器对他的支持不是很好,我们需要babel来转换他。

npm install babel-core babel-loader babel-preset-env --save-dev
复制代码

bable的配置,需要创建一个文件去配置。 新建.babelrc文件,写入如下内容

{
  "presets": [
    "env"
  ]
}
复制代码

接下来需要配置babel-loader,可以在package.json文件配置,但是还是独立出去好,比较好维护。项目下新建一个webpack.config.js.加入一些基础配置。

// webpack v4
const path = require('path');
module.exports = {
  entry: { main: './src/index.js' },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      }
    ]
  }
};
复制代码

然后package.json的脚本可以去除一些配置.

"scripts": {
    "dev": "webpack --mode development",
  "build": "webpack --mode production"
  },
复制代码

然后再运行编译,也是可以正常编译。

Html && Css

dist文件夹下新建一个index.html的文件.

<html>
  <head>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <div>Hello, world!</div>
    <script src="main.js"></script>
  </body>
</html>
复制代码

上面这段代码,使用到了style.css. 接来下去处理css的问题. src文件夹下新建style.css

div {
  color: red;
}
复制代码

然后在js文件中引入css.,打开index.js文件

import "./style.css";
console.log("hello, world");
复制代码

解析来我们就需要配置css的规则,打开webpack.config.js

// webpack v4
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin'); //新加入

module.exports = {
  entry: { main: './src/index.js' },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract(
          {
            fallback: 'style-loader',
            use: ['css-loader']
          })
      }// 新加的css 规则
    ]
  }
};

复制代码

上面我们用了一些插件和加载器.需要去安装.

npm install extract-text-webpack-plugin --save-dev
npm install style-loader css-loader --save-dev
复制代码

上面我们提出css来编译,你可以看到他的规则, 规则可以这样认为

{
        test: /\.拓展名$/,
        exclude: /不需要执行的文件夹/,
        use: {
          loader: "你的加载器"
        }
}
复制代码

我们需要extract-text-webpack-plugin这个提取插件,因为webpack只会辨别js.这里需要通过ExtractTextPlugin获取css文本进行压缩。

我们再次尝试编译,npm run dev发现会有报错,这个是因为这个提取器在新版本的原因。相关报错Webpack 4 compatibility 可以解决这个问题,那就是换个版本。

npm install -D extract-text-webpack-plugin@next
复制代码

然后再编译,发现可以来,同时再dist下有一个style.css文件。

这时候package.json的依赖文件如下

"devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.4",
    "babel-preset-env": "^1.6.1",
    "css-loader": "^0.28.11",
    "extract-text-webpack-plugin": "^4.0.0-beta.0",
    "style-loader": "^0.20.3",
    "webpack": "^4.4.1",
    "webpack-cli": "^2.0.12"
  }
复制代码

下面我们来配置支持scss

npm install node-sass sass-loader --save-dev
复制代码

我们在src下新建一个index.html

<html>
  <head>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <div>Hello, world!</div>
    <script src="main.js"></script>
  </body>
</html>
复制代码

安装html插件

npm install html-webpack-plugin --save-dev
复制代码

安装完成之后来修改webpack.config.js

// webpack v4
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');// 新加

module.exports = {
  entry: { main: './src/index.js' },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract(
          {
            fallback: 'style-loader',
            use: ['css-loader']
          })
      }// 新加
    ]
  },
  plugins: [
    new ExtractTextPlugin({filename: 'style.css'}),
    new HtmlWebpackPlugin({
      inject: false,
      hash: true,
      template: './src/index.html',
      filename: 'index.html'
    })// 新加

  ]
};

复制代码

这个是最终的html的一个模版. 现在html,css,js基本配置的差不多,我们删除dist来试试。

rm -rf dist/
npm run dev
复制代码

这时候会发现dist下存在js,css,html文件.

缓存

可以查看关于hash缓存的文档来使浏览器只请求改变的文件.

webpack4提供了chunkhash来处理。

来看看:

// webpack v4
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');// 新加

module.exports = {
  entry: { main: './src/index.js' },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[chunkhash].js' //changed
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract(
          {
            fallback: 'style-loader',
            use: ['css-loader']
          })
      }// 新加
    ]
  },
  plugins: [
    new ExtractTextPlugin(
      {filename: 'style.[chunkhash].css', disable: false, allChunks: true}
    ), //changed
    new HtmlWebpackPlugin({
      inject: false,
      hash: true,
      template: './src/index.html',
      filename: 'index.html'
    })

  ]
};

复制代码

然后src下的html也要修改

<html>
  <head>
    <link rel="stylesheet" href="<%=htmlWebpackPlugin.files.chunks.main.css %>">
  </head>
  <body>
    <div>Hello, world!</div>
    <script src="<%= htmlWebpackPlugin.files.chunks.main.entry %>"></script>
  </body>
</html>
复制代码

可以发现这里改变来,这个是使模版使用hash.

好了,现在可以编译,会发现dist下的css和js名字是带有hash指的。

缓存带来的问题,如何解决

如果我们改变代码,在编译的时候,发现并没有生成创新的hash名文件。

div {
  color: 'red';
  background-color: 'blue';
}
复制代码

再次进行编译npm run dev,发现并没有生产新的hash文件名称,但是如果改变js代码,再次编译,会发现是改变了hash名称

import "./index.css"
console.log('Hello, world!');
复制代码

如何解决?

两种办法:

  • 方法1 把css提取器中的[chunkhash]换成[hash].但是这个会与webpack4.3中的contenthash有冲突.可以结合webpack-md5-hash一起使用。

npm install webpack-md5-hash --save-dev

// webpack v4
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash'); //新加
module.exports = {
  entry: { main: './src/index.js' },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[chunkhash].js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract(
          {
            fallback: 'style-loader',
            use: ['css-loader']
          })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin(
      {filename: 'style.[hash].css', disable: false, allChunks: true}
    ),//changed
    new HtmlWebpackPlugin({
      inject: false,
      hash: true,
      template: './src/index.html',
      filename: 'index.html'
    }),
    new WebpackMd5Hash() //新加

  ]
};

复制代码

然后编译查看是否改变。 现在的变化是,改变css文件,那么css文件的hash名字改变。如果改变js文件,那么css和js的压缩hash名称都将改变。

  • 方法2(推荐)

方法1可能还会存在其他的冲突,所以来尝试下mini-css-extract-plugin

这个插件是为了取代extract-plugin, 并带来兼容性的改变

npm install --save-dev mini-css-extract-plugin

尝试使用

// webpack v4
const path = require('path');
// const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");//新加

module.exports = {
  entry: { main: './src/index.js' },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[chunkhash].js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      // {
      //   test: /\.css$/,
      //   use: ExtractTextPlugin.extract(
      //     {
      //       fallback: 'style-loader',
      //       use: ['css-loader']
      //     })
      // }
      {
        test: /\.(scss|css)$/,
        use:  [  'style-loader', MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
      } // 新加
    ]
  },
  plugins: [
    // new ExtractTextPlugin(
    //   {filename: 'style.[hash].css', disable: false, allChunks: true}
    // ),
    new MiniCssExtractPlugin({
      filename: 'style.[contenthash].css',
    }),//新加
    new HtmlWebpackPlugin({
      inject: false,
      hash: true,
      template: './src/index.html',
      filename: 'index.html'
    }),
    new WebpackMd5Hash()

  ]
};

复制代码

好了,接下来我们尝试改变文件会怎么变化。 改变css,进行编译发现只有css的文件改变来。改变js文件,发现编译之后只有js的hash名称改变,不错,就是这样。

继承PostCss

postcss大家应该不会陌生了。

npm install postcss-loader --save-dev
npm i -D autoprefixer
复制代码

-D.

创建postcss.config.js

module.exports = {
    plugins: [
      require('autoprefixer')
    ]
}
复制代码

然后来配置你的webpack.config.js

// webpack v4
const path = require('path');
// const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: { main: './src/index.js' },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[chunkhash].js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        test: /\.(scss|css)$/,
        use:  [  'style-loader', MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader']//changed
      }
    ]
  },
  plugins: [
    // new ExtractTextPlugin(
    //   {filename: 'style.[hash].css', disable: false, allChunks: true}
    // ),
    new MiniCssExtractPlugin({
      filename: 'style.[contenthash].css',
    }),
    new HtmlWebpackPlugin({
      inject: false,
      hash: true,
      template: './src/index.html',
      filename: 'index.html'
    }),
    new WebpackMd5Hash()

  ]
};

复制代码

保持dist整洁

这里使用clean-webpack-plugin插件.

npm i clean-webpack-plugin --save-dev

// webpack v4
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin');//新加

module.exports = {
  entry: { main: './src/index.js' },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[chunkhash].js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        test: /\.(scss|css)$/,
        use:  [  'style-loader', MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader']//changed
      }
    ]
  },
  plugins: [
    // new ExtractTextPlugin(
    //   {filename: 'style.[hash].css', disable: false, allChunks: true}
    // ),
    new CleanWebpackPlugin('dist', {} ),//新加
    new MiniCssExtractPlugin({
      filename: 'style.[contenthash].css',
    }),
    new HtmlWebpackPlugin({
      inject: false,
      hash: true,
      template: './src/index.html',
      filename: 'index.html'
    }),
    new WebpackMd5Hash()

  ]
};

复制代码

这样每次编译的时候,就会清空dist文件夹

最终代码

相关文章:

  • 5s管理推进的三个阶段及三大实施原则
  • 小程序生命周期流程
  • 前端缓存-IndexedDB
  • 生产LVS负载均衡与keepalive的高可用实践
  • SQL数据库字段数据类型详细说明
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • Mysql密码重置
  • hadoop之旅6-windows本地MapReducer离线单词统计
  • 获取全局上下文(getApplicationContext)_创建Shared Preference工具类_实现自动登录
  • 【火炉炼AI】机器学习053-数据降维绝招-PCA和核PCA
  • 兄弟连区块链教程Fabric1.0源代码分析Ledger(账本)一
  • 简单远程遥控程序【网络程序设计 - 简单远程遥控程序,C实现】
  • CStringArray error C2248: 'CObject::CObject' : cannot access private member declared in class
  • js 在光标处插入内容
  • fastcgi_param 详解
  • hexo+github搭建个人博客
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • JavaScript设计模式之工厂模式
  • k8s如何管理Pod
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • markdown编辑器简评
  • PHP的类修饰符与访问修饰符
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • uva 10370 Above Average
  • 简单实现一个textarea自适应高度
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 异步
  • 7行Python代码的人脸识别
  • 树莓派用上kodexplorer也能玩成私有网盘
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • ( 用例图)定义了系统的功能需求,它是从系统的外部看系统功能,并不描述系统内部对功能的具体实现
  • (33)STM32——485实验笔记
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • (转)大型网站架构演变和知识体系
  • (转)关于如何学好游戏3D引擎编程的一些经验
  • ***原理与防范
  • .NET CORE Aws S3 使用
  • .NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库
  • .Net(C#)自定义WinForm控件之小结篇
  • .NET/C# 获取一个正在运行的进程的命令行参数
  • .NET简谈互操作(五:基础知识之Dynamic平台调用)
  • .NET正则基础之——正则委托
  • [android] 练习PopupWindow实现对话框
  • [javaSE] 数据结构(二叉查找树-插入节点)
  • [msg_msg] corCTF2021 -- fire_of_salvation
  • [NOIP2007 普及组] 纪念品分组--贪心算法
  • [Oh My C++ Diary]类继承和类组合(内嵌类)初始化的不同
  • [osgearth]通过API创建一个earth模型
  • [Python3网络爬虫开发实战] 5.3-非关系型数据库存储