webpack 4.x.x 搭建项目完整详解步骤

4,934 阅读9分钟

前言

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

从 webpack v4.0.0 开始,可以不用引入一个配置文件。然而,webpack 仍然还是高度可配置的。在开始前你需要先理解四个核心概念:

  • 入口(entry)
  • 输出(output)
  • loader
  • 插件(plugins)

本文档旨在给出webpack的入门使用。

一、新建项目webpack1.0.0,初始化package.json文件

输入命令

mkdir webpack1.0.0   // 第一步创建项目webpack1.0.0
cd ./webpack1.0.0    // 进入项目路径   
npm  init            // 初始化package.json 文件

二、项目安装webpack webpack-cli webpack-dev-server插件,为webpack项目提供相应的安装包。

输入命令:

npm install webpack webpack-cli webpack-dev-server

命令完成后,我们会发现项目中多了一个 node_modules 文件夹,该文件夹是用来存放项目中安装的依赖包,无需画较大的精力关注,有深入学习的同学可以在后期慢慢深入了解如何构建一个npm安装包,本文不作介绍。

三、完整项目目录及项目文件

3.1为项目创建三个文件夹(config --配置文件夹 dist --编译文件夹 src --项目正文文件夹)

输入命令:

mkdir config dist src

如图增加了三个文件夹:

3.2、创建项目入口html、js文件

输入命令:

touch dist/index.html src/index.js
//该命令window系统不支持,请手动创建

四、执行webpack 打包命令。

4.1 在package.json -> scripts 栏目 配置build的运行命令。配置如图所示

配置完成后运行命令:

npm run  build

执行命令后大家会发现,大家会发现dist文件夹下多了个main.js,命令运行时,npm取出build对应配置的命令在node环境中执行,webpack打包默认入口为src/index.js, 默认打包模式为 --model development, 打包模式总共有两种:

  • --model development(开发环境)
  • --model production(生产环境)

生成环境的命令配置如图:

配置完成后运行命令:

npm run  build:prod

命令执行后结果如上述一致,黄色的警告提示消失了,打包的文件会更小。

以上操作完成后webpack的初步打包过程就有所了解啦,但是真实项目中webpack怎么可能这么简单的使用,接下来我们要讲讲webpack的重点了,从以上的结果我们不难发现webpack有编码打包编译的功能,但是要在大型项目中运用自如我们就要掌握webpack的打包配置文件书写了,下面来一一介绍webpack的配置文件具体内容。

五、webpack 配置文件结构介绍

5.1 webpack打包配置文件介绍及启用

从 webpack v4.0.0 开始,可以不用引入一个配置文件。然而,webpack 仍然还是高度可配置的。在开始前你需要先理解四个核心概念:

  • 入口 ------ (entry) 打包文件的入口(对应上述默认入口src/index.js),支持多入口
  • 输出 ------ (output) 打包压缩文件后的输出位置
  • 加载器 ---- (loader) 针对对应文件进行转义,解析 成浏览器识别的文件
  • 插件 ------ (plugins) 插件目的在于解决 loader 无法实现的其他事。

讲了概念过后,接下来我们创建一个webpack.dev.js, 做一个简单的配置解析。

touch config/webpack.dev.js
//该命令window系统不支持,请手动创建

配置文件类容,及配置介绍

const HtmlWebpackPlugin = require('html-webpack-plugin'); //通过 npm 安装
const path = require('path');        //node内置path模块,该模块主要集成文件系统路径操作API

const config = {
    mode: 'development',        //webpack打包的模式,上述命令里有介绍,也可以在本配置中配置
    entry: {    //js的入口文件,支持多入口 注释①
        main: path.resolve(__dirname,'../src/index.js')
    },
    output: {   //js打包压缩后的出口文件,多入口时对应的配置应做相对变化 注释②
        path: path.resolve(__dirname,'../dist'),
        filename:'bundle.js'
    },
    module: {
        rules: [] // 配置loder使用的规则、作用范围、控制输出的名称、位置等;主要作用是编译,解析文件; 暂时不使用loader
    },
    plugins: [
        new HtmlWebpackPlugin({template: './src/index.html'})  //根据项目提供HTML模板,生成新页面,并将对应的输出打包压缩输出的js,链接到页面中;详细配置见注释④
    ]
};

module.exports = config;

下面对代码的注释出做一个详细介绍的链接导向(建议在本文完全看完后、再去做详细深入了解):

打包入口详解-注释①

打包输出详解-注释②

HTML模板插件详解-注释④

下面我们把上述 一 ~ 三节完成的项目里的项目内容进行下调整,我们把dist中文件清空,并在src文件夹中添加 index.html 模板HTML,完成后文件目录如图:

接下来,我们使用 npm install html-webpack-plugin 将项目中使用的未安装的包安装了。剩下的操作是我们重新配置下webpack打包的命令,第三节我们有介绍在package.json 文件中配置运行命令;下面我们贴出package.json代码:

{
  "name": "webpack-1.0",
  "version": "1.0.0",
  "description": "webpacke基础训练",
  "author": "张啸",
  "license": "ISC",
  "main": "index.js",
  "scripts": {  //npm run 运行的命令配置
    "build": "webpack --config config/webpack.dev.js"  //打包命令的配置 --config表示以何种文件配置方式启动项目打包
  },
  "dependencies": {   //项目所需要的第三方安装包
    "webpack": "^4.29.6",
    "webpack-cli": "^3.2.3",
    "webpack-dev-server": "^3.2.1"
  }
}

命令行运行下面命令:

npm run build

运行过后的结果如图所示:

打包后生成了index.html 并且引入了output中的打包压缩后的JS文件。综合上述一个简单的项目打包就完成了,但是大家有没有发现,这些只是打包了,并不适合在开发的过程中使用,那在开发的时候我们更想直接去流浪器查看开发项目的直接页面。这时候我们就要用到webpack-dev-server插件了,这个插件是干嘛的呢?

5.2 webpack-dev-server 启动服务及命令参数

webpack-dev-server的作用是打包项目后,并启动一个服务,可以直接在浏览器查看项目页面。 具体配置如下,webpack.dev.js添加devserver修改下:

const HtmlWebpackPlugin = require('html-webpack-plugin'); //通过 npm 安装
const path = require('path');        //node内置path模块,该模块主要集成文件系统路径操作API

const config = {
    mode: 'development',        //webpack打包的模式,上述命令里有介绍,也可以在本配置中配置
    entry: {    //js的入口文件,支持多入口 注释①
        main: path.resolve(__dirname,'../src/index.js')
    },
    output: {   //js打包压缩后的出口文件,多入口时对应的配置应做相对变化 注释②
        path: path.resolve(__dirname,'../dist'),
        filename:'bundle.js'
    },
    module: {
        rules: [] // 配置loder使用的规则、作用范围、控制输出的名称、位置等;主要作用是编译,解析文件; 暂时不使用loader
    },
    plugins: [
        new HtmlWebpackPlugin({template: './src/index.html'})  //根据项目提供HTML模板,生成新页面,并将对应的输出打包压缩输出的js,链接到页面中;详细配置见注释④
    ],
    devServer: {        //webpack-dev-server配置(仅开发环境需要)
		contentBase: path.join(__dirname, './dist'), //编译打包文件的位置
		publicPath: '/',    
		port: 8080,                 //服务器端口号
		host: '0.0.0.0',
		proxy: {},                  //代理列表
		compress: true,
		historyApiFallback: true,   //开启服务器history重定向模式
	}
};
module.exports = config;

package.json 文件添加开发启动命令,如下:

{
  "name": "webpack-1.0",
  "version": "1.0.0",
  "description": "webpacke基础训练",
  "main": "index.js",
  "scripts": {
    "build": "webpack --config config/webpack.dev.js",
    "dev" : "webpack-dev-server --config config/webpack.dev.js --color --progress --hot" // --color 启用彩色打印  --progerss 启用进程监测 --hot 启用热加载
  },
  "author": "张啸",
  "license": "ISC",
  "dependencies": {
    "babel-loader": "^8.0.5",
    "html-webpack-plugin": "^3.2.0",
    "webpack": "^4.29.6",
    "webpack-cli": "^3.2.3",
    "webpack-dev-server": "^3.2.1"
  }
}

如上我们有添加了webpack-dev-server 命令,下面我们启动项目查看结果:

npm run dev

打开页面http://localhost:8080/查看结果如图

以上是一个简单webpack全过程运用的例子了,下面我给大家推荐一些webpack常用的一些loader、plugins的使用。

六、webpack项目中常用loader,以及配置。

6.1 JavaScript方面的所运用的loader

  • "babel-core" //JavaScript编译核心babel-core(必须)
  • "babel-loader" //JavaScript编译babel-loader(必须)
  • "babel-plugin-transform-runtime" //JavaScript 运行环境转换器
  • "babel-preset-stage-0" //ES6,ES7语法转换ES5编译器(ES7的提案,且包含了stage-2,stage-1所有功能)
  • "babel-polyfill" //IE低版本扩展JS某些API(如promise object.defindproperty)(根据项目需求是否兼容IE低版本安装)
  • "babel-runtime" //提供将ES6转变成ES5运行环境,并不污染全局完成代码填充
  • "babel-plugin-transform-decorators-legacy" //JavaScript 装饰器语法编译器(使用@语法需添加)
  • "babel-plugin-transform-react-jsx" //react jsx语法转换器
  • "babel-plugin-react-html-attrs" //react dom属性识别语法转换器
  • "babel-preset-react" //react语法编译器 以上都是babel loader 相关的loader包,当然项目使用babel-loader前,还需要配置一个babel配置,通知babel-loader在使用时对应的语法文件采用何种方式去处理。该配置文件名称为 .babelrc; babelrc配置如下:
{
    "presets": [
        "env",
        "react",
        "stage-0"
    ],
    "plugins": [
        "transform-decorators-legacy",
        "transform-react-jsx",
        [
            "transform-runtime",
            {
                "helpers": false,
                "polyfill": false,
                "regenerator": true,
                "moduleName": "babel-runtime"
            }
        ],
        "react-html-attrs"
    ]
}

在 webpack.dev.js -> module.rules 选项添加loader规则; 添加配置如下:

module: {
    rules: [{
      test: /\.js$/,
      loader: "babel-loader",
      options: {
        cacheDirectory: false,
        babelrc: true
      },
      exclude: path.resolve(__dirname, 'node_modules/'),
    }]
}

babelrc配置详情可见官网

6.2 CSS方面的所运用的loader

  • "style-loader" //样式loader(必须)
  • "css-loader" //css-loader (必须)
  • "autoprefixer" //css3自动补全功能
  • "postcss-cssnext" //利用cssnext 额外增加的一些 css 规范,
  • "postcss-loader"
  • "less": //以下都是使用less相关语法加载库
  • "less-loader"
  • "node-sass": "^4.5.3", //以下都是使用sass,scss相关语法加载库
  • "sass-loader": "^6.0.6",

同样用到postcss-loader的话依然需要有配置告诉loader以何种方式编译css。配置文件postcss.config.js如下:

module.exports = {
    plugins: {
        'postcss-cssnext': {},
    }
};

postcss配置详情可见官网

在 webpack.dev.js -> module.rules 选项添加loader规则; 添加配置如下:

module: {
    rules: [{
			test: /\.css$/,
			use: [{
					loader: 'style-loader',
					options: { sourceMap: false }
				}, {
					loader: 'css-loader',
					options: { sourceMap: false}
				}, 'postcss-loader',
			]
	},{
      test: /\.less$/,
      use: [
        {loader: 'style-loader', options: {sourceMap: false}},
        {loader: 'css-loader', options: {sourceMap: false}},
        {loader: 'postcss-loader', options: {sourceMap: false}},
        {loader: 'less-loader', options: {sourceMap: false}}
      ]
    }, {
      test: /\.(scss|sass)$/,
      use: [
        {loader: 'style-loader', options: {sourceMap: false}},
        {loader: 'css-loader', options: {sourceMap: false}},
        {loader: 'postcss-loader', options: {sourceMap: false}},
        {loader: 'sass-loader', options: {sourceMap: false}}
      ]
    }]
}

6.3 资源文件加载的所运用的loader

  • "file-loader" 文件处理loader
  • "url-loader" url链接处理loader

在 webpack.dev.js -> module.rules 选项添加loader规则; 添加配置如下:

module: {
    rules: [{
      test: /\.(png|jpg|gif|ico|jpeg|bmp|swf)$/,
      exclude: path.resolve(__dirname, 'node_modules/'),
      use: [{
        loader: 'url-loader',
        options: {
          limit: 10000,
          name(file) { //图片超过 10000 Kb处理
            return file.replace(/.*assets(\/|\\)/, '').replace(/\\/g, '/')
          }
        }
      }]
    }, {
      test: /\.(woff|woff2|svg|eot|ttf|otf)$/,
      exclude: path.resolve(__dirname, 'node_modules/'),
      use: [{
        loader: 'file-loader',
        options: {
          limit: 10000,
          name: 'fonts/[name].[ext]'
        }
      }]
    }]
}

webpack的loader种类和用途十分繁多,这里列举了几个常用loader,有兴趣的同学可以去官网查看,本文只适合webpack入门新手查阅

七、webpack项目中常用plugins,以及配置。

7.1 常用插件

  • HtmlWebpackPlugin 模板生成HTML并链接入口js插件
  • inline-manifest-webpack-plugin manifest 缓存配置插件
  • copy-webpack-plugin 文件拷贝插件
  • dotenv-webpack 环境变量载入插件
  • webpack-parallel-uglify-plugin js压缩插件
  • optimize-css-assets-webpack-plugin css提取插件
  • mini-css-extract-plugin css压缩插件

在 webpack.dev.js -> plugins 选项添加插件使用规则; 添加个别插件配置如下:

plugins: [
	new webpack.DefinePlugin({  //环境变量装配
		'process.env': {
			NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development'),
			NODE_APIENV: JSON.stringify(process.env.NODE_APIENV || 'development'),
			WITH_TRACKER:process.env.WITH_TRACKER
		},
	}),
	new CopyWebpackPlugin([{    //文件拷贝
		from: path.resolve(__dirname, '../static'),
		to: path.posix.join('static'),
		ignore: ['.*']
	}, {
		from: path.resolve(__dirname, '../app/assets/javascripts'),
		to: path.posix.join('javascripts'),
		ignore: ['.*']
	}]),
]

这里就不一一介绍各个插件的使用规则及配置参数了,大家可以根据插件官网进行翻阅