从零开始学webPack 完整实现流程,搭建中等体量前端项目

本文详细介绍了从零开始使用webpack搭建一个中等规模前端项目的全过程,包括全局安装node和webpack,创建项目文件夹,初始化package.json,安装依赖,配置打包模式,创建html文件,优化配置等步骤。同时,文中还提到了如何引入本地服务,配置不同环境下的资源文件路径,以及使用loader处理各种文件类型。
摘要由CSDN通过智能技术生成

创建项目配置项目这些,不常用是真的记不住。

创建一个舒适的webpack项目,要查找三四篇教程,碰到水平比较高的教程,还要再查另外的教程对比,真累。自我总结学习。如果还能帮到看文章的人,就更有意义了。

从0到1全局安装node,webpack。

先下载node安装完,node是环境。然后全局安装webpack/webpack-cli。npm install webpack webpack-cli –g。
之后,就可以创建你的项目文件夹,然后再该文件夹中打开cmd/npm/cnpm进入下一步。
cnpm和npm的区别大概就是cnpm是个镜像,不用连接国外资源,下载可能更快一点,了解更多可以百度。

从0到1创建项目文件夹,打开cmd或者npm/cnpm,初始化项目

tips:在项目文件夹中,按住键盘的shift键,同时点击右键,会出现一个新的选项,选择打开PowerShell,即进入npm窗口。也可以cmd,然后cd到你的目录下。
执行命令:> npm init 或者 npm init -y
仅执行init是需要手动填写包括项目名、描述、作者名等一系列信息。
添加-y默认全部选yes,按照默认走,生成package.json之后,可以在代码中修改、增加你的相关信息。
init之后,文件夹内生成了一个package.json文件
JSON文件中有个main参数,默认为index.js,此配置为项目基本打包配置的入口文件,然后:

webpack npm install webpack -g //全局创建webpack
npm install webpack --save-dev //单独在项目中创建

之前已经全局安装过webpack,也需要进行一次-D的安装,否则:

npm WARN clean-webpack-plugin@3.0.0 requires a peer of webpack@* but none is installed. You must install peer dependencies yourself.

同时,npm install webpack 还生成了一个node_modules文件夹(存放当前依赖),以及package-lock.json文件(存放当前依赖及版本号等信息)。每次npm install + 依赖名 ,都会存放在这里。
在下载、转移、提交项目的时候,可以不转移package-lock.json和node_modules,只转移package.json文件以及源文件,然后直接在命令框内输入npm i即可。

1块钱它什么都干不了,还差很多

在大部分教程中,一个基础项目已经创建成功。
但是!如果想要将这个项目投入使用,还差很多。
还需要配置各种信息,以引入各项依赖、源文件、配置打包模式、最终打包生成可以发布在服务器上的完整代码

1.完善项目-创建文件夹进行分类管理,并安装依赖

npm init 之后,文件夹内只有package.json文件,这时需要完善项目,使项目更加友好。
接下来,安装一些依赖、创建一些配置文件,来优化打包。优化之后还要开始写功能代码,实现页面及功能。
首先,为了便于区分管理,创建几个文件夹的来分别储藏。
1.1创建文件夹
所有的文件夹都只是为了便于管理,如果都在根目录,那是一个灾难。
config文件夹,配置信息文件。
src文件夹,源文件,存放页面功能代码,还可以继续向下创建pages、js、css、image等文件夹来进行区分存放文件。

1.2安装必要的依赖,并创建配置文件

先上代码

在命令框中执行下列命令

npm install webpack-dev-server --save-dev
npm install glob -save-dev
npm install html-webpack-plugin --save-dev
npm install clean-webpack-plugin --save-dev
npm install uglifyjs-webpack-plugin --save-dev
npm install optimize-css-assets-webpack-plugin --save-dev
npm install purifycss-webpack --save-dev

推荐再安装一个“happypack”,可以多进程发动打包:
https://www.jianshu.com/p/b9bf995f3712
另外推荐再安装 bable,可以支持ES6/typescripts等多种语法,这个挂在下方loader部分做大概说明。
上面代码按照顺序说明:
所有依赖包都可以在https://www.npmjs.com中搜索到,相关配置也都有说明。

1.安装webpack-dev-server依赖,可以创建本地服务器进行代码调试。
2.安装glob依赖,便于处理文件路径参见)。
3.安装html-webpack-plugin依赖,简化创建html文件。
4.安装clean-webpack-plugin依赖,每次打包时自动删除之前打包的文件。
5.安装uglifyjs-webpack-plugin依赖,用于压缩打包的js文件。参见
6.安装optimize-css-assets-webpack-plugin,压缩css参见)。
7.安装purifycss-webpack,进行css筛选,对没有用到的样式,不予打包参见1参见2

补充说明:
第七个的purifycss-webpack这个依赖已经弃用:npmjs.com中的相关说明一路按照npmjs推荐的去找,最终发现推荐的是purgecss-webpack-plugin这个新的依赖安装配置方法说明

此外,npm(nodePackageManager)中提供的依赖非常丰富,以简化css代码为例,还有如purify-css等。
https://www.npmjs.com

写的同时,我也在按照步骤创建一个新的webpack项目,以确保我的笔记能保证正确性。
出现报错信息也不用慌,先看一下报错信息,再查一下报错原因,然后对应解决。

如果要安装固定版本的依赖,可以写到package.json中配置,也可以用命令行控制。
以server依赖为例,需要的版本号为3.2.1。
可以在json文件中的devDependencies中写入"webpack-dev-server": “^3.2.1”,然后在命令框中执行 npm i
或者直接在命令行中执行npm i -D webpack-dev-server@3.2.1

执行完上述安装过程之后,检查package.json,有新增。

“devDependencies”: {
"html-webpack-plugin": "^4.2.0",
“webpack”: “^4.43.0”,
“webpack-cli”: “^3.3.11”,
"webpack-dev-server": "^3.2.1"
...
}

3.安装 cross-env 依赖,以支持读取不同的webpack.config.js文件,这一点在我之前写的VUE创建项目说明中提到,地址附上。

为自己带颜:https://blog.csdn.net/x_r_fly/article/details/105637365

本文中采用的是另一种方法,脱离cross-env,在同一个webpack.config.js文件中识别不同的打包命令,并分别采用不同的域名,会在最后第4点记录说明。

方法可行性来源: http://nodejs.cn/api/process/process_argv.html

2.完善项目-配置package.json

package.json文件,是一个描述文件,描述了你的项目依赖那些包,同时允许我们使用“语义版本规则”,指明你项目依赖的版本。
安装依赖时,会在package.json中写入,package.json中有依赖时候,直接npm-install,也会从package.json中获取需要安装哪些。
执行完上述代码之后,json中的内容是init-y时候产生的默认描述信息(name、author、version等)、安装好的依赖信息(devDependencies和Dependencies),以及main和scripts项。
main配置,默认是index.js,上文已经作了说明。
scripts配置的则是脚本命令。
配置json文件主要是配置打包命令,以启动压缩打包、启动本地服务等。

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack --mode production",
    "build": "webpack --config config/webpack.build.config.js"
}

三行命令分别是:
1.test是默认生成,翻译发现,这是提示还没有设置打包命令,不理会。
2.添加dev命令此命令是webpack默认支持的打包方式
但是此时执行npm run dev命令时,会出现错误信息:

ERROR in Entry module not found: Error: Can't resolve './src' in 'D:\work\codes\MeC'

原因:

webpack默认读取根目录下的webpack.config.js获取配置信息。
根目录没有找到config文件,此时采用默认输入文件是src文件夹下的index.js,输出文件是dist文件夹下的main.js。
所以在执行dev下的打包命令时,因无法获取输入文件而报错。

解决办法:

在src目录下新建index.js文件,再执行npm run dev命令。
打包成功,在根目录下出现dist文件夹,并在其中输出打包后的main.js。

3.添加build命令此命令使用自己配置的处于config文件夹下的webpack.build.config.js文件。-.-config用于指定使用的配置文件,说来话长, 参见
此时还没有创建该文件,因此执行build会报错,接下来在config文件夹下创建webpack.build.config.js。
下一步,在webpack.build.config.js中引用已经安装好的依赖、配置输入输出文件。

3完善项目-引用webpack、path、glob,并配置输入输出文件。

安装好了依赖,不引用相当于没装,所以要配置引用的依赖。

3.1.引用依赖:
require和import引入文件的区别,参见这里
在config文件夹中创建webpack.build.config.js文件,并在package.json中配置scripts项,以调用对应的js文件。所有依赖的引用配置方法均可以在npmjs中找到,前面也有附上地址。

作为webpack框架,肯定引入webpack核心脚本,然后引入path和glob,用于解析路径。
配置module.exports,配置打包模式、输入、输出

//定义参数,这就是引用到的依赖了。
const webpack = require('webpack');
const path = require('path');
const glob = require('glob');

console.log('正在打包中...');

module.exports={
	mode:'production',
	entry:{
		main:'./src/index.js'
	},
	output:{
		path: path.resolve(__dirname, '../dist'),
		publicPath: '/',
		filename: '[name]-[hash].js',
		//一般懒加载/按需加载用
		//chunkFilename:'[name]-[chunkhash].js'
	}
}

其中,mode为打包模式,entry为入口项,output为出口项。
解释如下:
3.1.1 mode——打包模式。
在上文中,json中有配置打包命令
“dev”: “webpack --mode production”
指默认打包,并采用production模式,如果在专门配置的config.js中没有设置mode值,且在json文件中配置命令也没有标明mode模式,命令行会发出提醒,并默认采用production模式。
mode有三个值,分别为none、development、production,分别对应——不采取任何默认措施、采取开发模式的默认措施、采取生成模式的默认措施。

3.1.2 entry——入口文件配置。
有两种配置方式:参见
3.1.2.1—对象方法(多入口多文件配置)
文件各自配置,这方式在压缩时会采用配置项的数量去选择压缩多文件,会分别生成main.js、index.js两个文件。
3.1.2.2数组方法(单入口多文件配置)
在压缩时将main数组中的所有文件全部压缩在main.js文件中
3.1.2.3—字符串方法(没研究过)

个人理解:做项目时一般采用多入口,造轮子时一般采用单入口。
对象:entry:{
		main:'./src/index.js',
		index:'./src/index.js',
		string:['./src/index.js',' ./src/js/index.js']
	},
数组:entry:{
		main:['./src/index.js',' ./src/js/index.js']
	},
字符串:
	entry:'./src/index.js',

3.1.3. output为输出项
3.1.3.1path:所有输出文件的目标路径。即打包后文件在硬盘中的存储位置。
上述写法中的path.resolve,将根据config.js定位的’…/dist’相对路径转为绝对路径,在上文中有相关解释的链接。
3.1.3.2publicPath:输出解析文件的目录。
指定资源文件引用的目录打包后浏览器访问服务时的url路径中通用的一部分因为打包后的文件路径会变化publicPath就会对引入的资源的路径做对应的补全并不会对生成文件的路径造成影响参见
3.1.3.3filename输出的文件名
webpakc占位符[name][hash][chunkhash][id]等。
[name]是打包后文件名的定义,会直接去找入口文件配置的json键值作为文件名。
[hash]是这次打包的hash值
[chunkhash],每一个chunk自己的hash,这个又涉及到chunkFilename。
chunkFilename,懒加载/按需加载用的多,entry中没有写,却又需要被打包的文件 参见

至此,可以执行npm run build命令,通过配置的config.js文件打包,输入index.js,输出main.js。
如果出现报错 “Failed to parse package.json data.”,注意json中的严格模式。

4.引入本地服务并配置

1.在package.json中scripts项中添加“serve”,"serve": "webpack-dev-server --config config/webpack.build.config.js",以使用npm run serve命令启动本地服务。
2.在webpack.build.config.js中添加devServer配置。
直接上代码,常用的参数都写在这里,更多全部参数及键值参见

module.exports={
	mode:'production',
	entry:{...},
	output:{...},
//增加devServe,做本地服务配置
	devServer:{
		contentBase:path.resolve(__dirname,'../dist'),//指定content base设置的路径作为请求的资源路径
        host:'localhost',
        port:'8080',
        open:false,//自动拉起浏览器
        hot:true,//热加载
        stats: "errors-only",//仅精准报错。
        headers: {
            'Access-Control-Allow-Origin': '*'//允许所有请求到的数据正常返回,服务端也有对应的限制。跨域相关。
        },
		compress:false,//启用 gzip 压缩
		inline:true,//启用内联模式
		proxy:{// 配置代理
			"/api":{
				target: 'http://server.com',
				changeOrigin: true,
				pathRewrite: {
					'^/proxy': ''
				}
			},
		}
	}
}

然后在命令行执行 npm run build打包生成项目,然后执行npm run serve,项目成功启动本地服务。
在浏览器中打开本地服务地址,或者将devServer中的open项改为true,自动打开你的本地服务地址——localhost:8080。

如果浏览器缩放比例比较大,或者屏幕比较小的话,页面是这个样子的:
在这里插入图片描述

因为上述步骤中并没有引入html文件,也没有配置。所以在启动本地服务后,本地服务页面中展示的是打包后的文件列表:还自带查询功能~
在这里插入图片描述

5.引入loader(文件加载器)

loader是什么?为什么要用loader?loader有哪些特性
建议打开上方超链接, 通读一遍。
简而言之,loader 用于对模块的源代码进行转换。
首先安装各个loader
使用较多的有,file-loader、css-loader、style-loader、babel-loader、es3ify-loader等
1.安装file-loader、css-loader、style-loader。

npm install --D css-loader file-loader style-loader

2.安装postcss、autoprefixer,以支持普通css文件。

npm i -D postcss autoprefixer

3.安装html-withimg-loadel,可以解决 “html中直接使用img标签src加载图片的话,因为没有被依赖,图片将不会被打包”的问题。

npm install html-withimg-loader -D

4.安装babel,用于ES6预编译为ES5,参见入门教程,建议仔细看一遍,既有原理讲解,又有实操说明,是babel很好的入门教程。参见babel配置详细讲解

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

5.安装less-loadel,以支持less。需要支持sass就安装sass-loader。

npm i -D less-loader

6.选择性安装es3ify-loader,用于ES5预编译为ES3,以支持IE8以上。

npm i es3ify-loader -D

这些loader都不需在config.js中引入即可调用,但是在配置之前,我们需要引入一个小小的打包优化插件(plugin):happyPack。
在上文中简单提到了此插件,再次附上链接,主要作用是扩展进程,加快打包速度。如果之前没有安装,现在就可以安装了。

npm i -D happypack

然后再config.js中增加module项,设置rules。
关于123点中,相关的loader,均可点击此处了解更多loader!

const HappyPack = require('happypack');
const happyThreadPool = HappyPack.ThreadPool({
    size: 4	//开启几个子进程去处理这一类型的文件,默认是3个,类型必须是整数
})
...
module.exports = {
	mode:'production',
	entry:{...},
	output:{...},
	devServer:{...},
	module: {
		rules:[
			{
				test: /.js$/,
	            enforce: 'post',
				use: [
					{loader:'happypack/loader?id=babel'},
	            	{loader:'es3ify-loader'}
	            ],
	            exclude:path.resolve(__dirname,'node_modules')
			},
			{
				test: /\.(htm|html)$/,
				use: [
					{loader:'happypack/loader?id=html'},
					{loader:'html-withimg-loader'}
	            ],
	            exclude:path.resolve(__dirname,'node_modules')
			},
			{
		        test: /\.css$/,
		        use: [
		          	{loader: "style-loader/url"},
		          	{loader: "file-loader?name=css/[name].[ext]"},
		          	{
		          		loader: "postcss-loader",
		          		options: {
		          			plugins: [
		          				require("autoprefixer") /*在这里添加*/
		          			]
		          		}
		          	}
				]
			},
			{
				test:/\.less$/,
				use: [
		          	'style-loader',
		          	{ loader: 'css-loader', options: { importLoaders: 1 } },
		          	'less-loader'
		        ]
			}
		]
	},
	plugins:[
		new HappyPack({
            id: 'babel',
            loaders: ['babel-loader?cacheDirectory=true'],
            threadPool: happyThreadPool,
            verbose: true
        }),
        new HappyPack({
            id: 'html',
            loaders: ['html-withimg-loader?cacheDirectory=true'],
            threadPool: happyThreadPool,
            verbose: true
        }),
	]
}

以上暂时配置了js、html、css、less四个文件的模块及一个happyPack的插件。先运行一下打包命令,看看是否出现了问题。果然出现了新的问题。
Error: Can’t resolve ‘es3ify-loader’ ,发现没有安装es3ify-loader,但是却配置了es3ify-loader。
那么先不考虑es3,把es3改为babel,支持把ES6转为ES5。
js相关的es3ify-loader注释掉,替换成babel-loader。

// {loader:'es3ify-loader'}
{
	loader: 'babel-loader',
	options: {
		presets: ['@babel/preset-env']	//读取根目录.babelrc文件中的配置,没有配置会报错。
	}
}

有看到说,使用babel,需要在项目根目录配置.babelrc文件,或者在package.json中与scripts同级添加下面的代码(请自行采用严格模式):
“babel”: {“presets”: [“env”]}
或许是目前还没有需要预编译的ES6的代码,所以目前直接运行本地服务也没有出现报错的情况。
PS:因为是断断续续的梳理webpack创建项目,好累。

6.配置打包模式,及不同环境下的资源文件路径

nodejs之process,参见此处。
6.1打包模式:

按照上述步骤走下来,此时执行npm run build命令,命令行会出现提示:The ‘mode’ option has not been set,此时会默认按照production进行打包。当前package.json中的打包命令如下:

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack --mode production",
    "build": "webpack --config config/webpack.build.config.js",
    "serve": "webpack-dev-server --config config/webpack.build.config.js"
  },

如果想区分三种打包命令,解决办法有这么几种:
Ⅰ.在package.json的打包命令中,增加–mode,可以配置development/none/production

"ceshi": "webpack --mode development --config config/webpack.build.config.js",

Ⅱ.在打包命令中对serve命令做如下配置,并在config.js中配置。

"serve": "webpack-dev-server --config config/webpack.build.config.js --development",

config.js中获取配置的development信息,在标题“3.完善项目-引用webpack、path、glob,并配置输入输出文件”中已经有写过console.log方法,续写

console.log('查看argv:::'+process.argv);
var arguments = process.argv[4];
module.exports={
	mode: arguments=='--production'?'production':(arguments=='--development'?'development':'none'),
	entry : {...}
}

执行npm run serve 命令,此时能看到输出的arguments为一个数组:

D:\work\tools\nodejs\node.exe,
D:\work\codes\MeC\node_modules\webpack-dev-server\bin\webpack-dev-server.js,
--config,
config/webpack.build.config.js,
--development

第五项就是我们写入的–development。
通过三行判断写入mode。
为什么写第二个办法呢,是为了再同一个文件中引入不同环境的资源。

6.2 针对不同环境的打包,引入不同的资源路径。

先在src/index.js中写入我们在测试环境的资源路径,随便配置一下

const protocolStr = document.location.protocol
const test = 'test.com/';
window.Banse_Domain_test = protocolStr+'//www.'+test+'';

比较简单解决的办法,就是写三套不同的域名、参数等的配置文件,分别在不同的打包命令中引用不同的路径,但是会麻烦,因为config.js会随时添加新的文件,每次改三套,很麻烦,
所以在src/index.js中写入代码,通过process.env.NODE_ENV来获取当前打包模式,相关原理参见此处。

const env = process.env.NODE_ENV
const protocolStr = document.location.protocol
const test = 'test.com/';
const build = 'build.com/';
window.Banse_Domain_test = protocolStr+'//www.'+test+'';
if(env == 'development'){
	window.Banse_Domain_test = protocolStr+'//www.'+test+'';
}else if(env == 'production'){
	
	window.Banse_Domain_test = protocolStr+'//www.'+build+'';
}

7.创建html文件,完成项目创建

在src路径下创建,pages、js、css文件夹,分别存放对应文件,在pages中写入index.html。然后随便写入:

<h1>已经启动本地服务</h1>

然后在config.js中配置html打包,
之前有安装了html-webpack-plugin依赖,
首先引入依赖,然后在plugin中写入,

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

new HtmlWebpackPlugin({
		template: './src/pages/index.html', //指定要打包的html文件
		filename:'./index.html', //指定输出路径和文件名
		hash:true,
		inject: 'head',
		showErrors:true,
		minify: {
			minimize: false,
			removeConments: true,
			collapseWhitespace: true,
			minifyCSS: true,
			minifyJS: false,
		},
		chunks: ['main','index'],
		chunksSortMode:'manual',
})

此时再运行本地服务,就可以看到首页了。

8.优化配置

在最开始的时候,在1.2节中,安装了很多用于优化的依赖,1,2,3,4都已经在上文中用到,5,6,7这里以第5个精简js的uglifyjs-webpack-plugin为例来进行简单说明,
再次说明,基本上所有依赖的配置,均可在https://www.npmjs.com中查到说明。
首先引入,代码如下:

const uglifyjs = require('uglifyjs-webpack-plugin')

在module.exports中写入

	optimization: {
		minimizer: [
			new uglifyjs({
				test: /\.js(\?.*)?$/i,  //测试匹配文件,
				include: /\.js(\?.*)?$/i, //包含哪些文件
			}),
		],
	},

其他的配置就不在这里多写了,看这里!!!!

9 补充,引入jquery,

安装jquery,npm install jquery -D
在config.js中,plugin下,添加webpack的主依赖语言。

plugin:[
	new webpack.ProvidePlugin({
		$: "jquery",
		jQuery: "jquery"
    }),
]

应该没有疏漏的地方了吧,其他的性能优化,seo优化,后续有时间再写吧,这一篇搞了一两个月,好累。

后续有精力继续努力研究吧。

此处附上别人写的关于webpack项目引入bootstrap的文章:
https://www.csdn.net/gather_21/NtzaYgxsNTA2LWJsb2cO0O0O.html

加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值