Webpack入门安装及配置

Javascript模块化

  1. CommonJS:是服务器端模块的规范,Node.js采用了这个规范。根据CommonJS规范,一个单独的文件就是一个模块。加载模块使用require方法,该方法读取一个文件并执行,最后返回文件内部的exports对象。CommonJS 加载模块是同步的,所以只有加载完成才能执行后面的操作。像Node.js主要用于服务器的编程,加载的模块文件一般都已经存在本地硬盘,所以加载起来比较快,不用考虑异步加载的方式,所以CommonJS规范比较适用。但如果是浏览器环境,要从服务器加载模块,这是就必须采用异步模式。所以就有了 AMD CMD 解决方案。
  2. AMD规范:是 RequireJS在推广过程中对模块定义的规范化产出,异步模块定义,define定义模板,require引用模板。
  3. CMD规范:是 SeaJS 在推广过程中对模块定义的规范化产出,module.exports定义模板,require引用模板。
    备注:CMD推崇依赖就近,AMD推崇依赖前置
  4. UMD规范:通用模板定义,既兼容AMD也兼容CommonJs,UMD是AMD和CommonJS的糅合
  • AMD模块以浏览器第一的原则发展,异步加载模块
  • CommonJS模块以服务器第一原则发展,选择同步加载,它的模块无需包装(unwrapped modules)。
    UMD先判断是否支持Node.js的模块(exports)是否存在,存在则使用Node.js模块模式。
    再判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块。
    前端模块规范

webpack介绍

Webpack是一个现代Javascript应用程序模块打包器(module bundler)。当Webpack处理应用程序时,它会递归地构建一个一个依赖关系图,可以把项目的各种js文件css文件等打包合并成一个或多个文件,其中包含应用程序需要的每个模块,然后将所有这些模块打包成少量的bundle-通常只有一个,由浏览器加载。

webpack官网:https://www.webpackjs.com/
webpack安装文档参考:https://www.webpackjs.com/guides/installation/
html-webpack-plugin文档参考:https://github.com/jaketrent/html-webpack-template
webpack官网

系统环境安装Node.js最新版本

目的:随同NodeJs集成的包管理工具(npm),从NPM服务器下载别人编写的第三方包到本地使用。

// 全局安装(一对多)
npm insatll <package name> -g
// 局部安装(一对一)
npm install <package name> --save-dev

安装淘宝镜像:npm install cnpm -g
检查webpack版本:cnpm -v

生成package.json文件

	npm init

package.json文件:定义了这个项目所需要的各种模块,以及项目配置信息(如名称、版本、许可证等元数据)。npm install命令根据这个配置文件,自动下载所需的模块

npm脚本

package.json中的script设置快捷方式,script指定了运行脚本命令的npm命令行缩写:

"script"{
	“build”:“webpack”
}

备注:script需要依赖webpack配置文件
先 init 初始化再安装webpack,package.json 就不会产生很多webpack的依赖。

安装webpack和webpack-cli

	npm install webpack webpack-cli --save-dev

配置webpack.config.js文件

自己在根目录下新建一个webpack.config.js,全局导出,所有文件都能访问,以下为该文件的配置信息以及解释:

	// path为node自带的路径模板
	const path = require("path");
	const HtmlWebpackPlugin = require('html-webpack-plugin');
	
	// 全局导出,让所有的文件都能访问当前的配置信息
	module.exports = {
	    // 开发模式development和生产模式production(一般用开发模式)
	    mode: "development",
	    // 入口文件(要打包的文件信息),有三种格式
	    // String 格式(单个入口文件)
	    // entry: './src/index.js',
	
	    // Array 格式(多个入口文件)
	    // entry: ['./src/index.js','./src/common.js'],
	
	    // Object 格式(多个入口文件)
	    entry: {
	        common: './src/common.js',
	        index: './src/index.js'
	    },
	    // 出口文件(要输出打包的文件信息)
	    output: {
	        //这里的路径需要绝对路径
	        path: path.resolve(__dirname,'./dist'),
	        // filename: 'js/index.js',       // 用于单个入口点
	        // filename: 'js/[name].js',      // 用于多个入口点
	        filename: 'js/[chunkhash].js'     // 用于多个入口点,且长效缓存,如71c5d2f31829ccc70a4e.js
	    },
	    // 文件监视改动,自动产出build.js,但还是需要手动刷新浏览器
	    watch: true,
	    // 插件
	    plugins: [
	        new HtmlWebpackPlugin({
	            title: 'webpack起步',  // 改变html中的title文本
	            template: './index.html',  // 打包的html文件,参照物,即模板路径
	            filename: 'index.html',    // 修改输出后的文件名
	            inject: 'head',     // 打包后的html中引入script文件的位置,默认为true,false的话不引入script文件,'head'在头部加载,'body'在头部加载
	            minify: {collapseWhitespace:true},  // 打包后的html文件去除空格,以及换行符,减小文件大小,节省空间
	            hash: true,   // 做cdn缓存,打包后的js文件后面会加上?标识,做缓存清缓存都通过标识,在本地服务器请求
	            chunks: ['index'],  // 加载哪些入口文件
	            excludeChunks: ['common'], // 除了哪些文件,其他的都加载
	        })
	    ]
	}

loader加载器

一、样式文件处理加载器

1. css-loader
遇到后缀为.css的文件,webpack先用css-loader加载器解析这个文件,最后计算完的css将会使用style-loader生成一个内容为最终解析完的style标签,放到head标签里面。

   // webpack.dev.config.js
   module:{
   	loaders:[
   		{
   			test: /\.css$/,  // 文件名以.css为后缀的文件
   			loader: "style-loader!css-loader"
   		}
   	]
   }

2. less-loader
先安装less才能写.less文件

    npm install less-loader -D

-D 安装的开发依赖是辅助工具,版本号会在package.json的devDependencies显示,-S安装的运行文件在源码之前运行(如vue,vueRouter,babel-polyfill等),版本号会在package.json的dependencies显示。

	// webpack.dev.config.js
	// 生命模块,包含多个loader
	module:{
		loaders:[
			{
				test: /\.less$/, // "/"是转义字符,“$”是以什么结尾
				loader: "style-loader!css-loader!less-loader" //先用less-loader,再用css-loader,最后是style-loader
			}
		]
	}

二、图片文件处理加载器(url-loader和file-loader)

	 npm install url-loader -D

bse64只会加载一次请求资源。

	// webpack.dev.config.js
	loaders:[
		{
			test:/\.(jpg|png|jpeg|gif|svg)$/,
			loader: 'url-loader?limit=4000'  // limit的值是自己设定的,对于图片大小小于limit的,使用base64编码,可以减少一次图片的网络请求;对于比较大的(超过limit)的图片,就不适合base64,编码和html混在一起,可读性差,html页面大小变大,拖慢了下载页面的速度,所以需要设置合理的limit。
		}
	]

添加webpack.dev.config.js和webpack.prod.config.js

通常项目会分成三个运行环境:开发人员在本地跑的开发环境(dev)测试人员用来做黑盒测试的测试环境(test)线上运行的生产环境(production)
dev和prod文件的基础代码从webpack.config.js复制过来,然后在package.json修改启动的配置:

	"script:"{
		// 运行后可以监听文件变化,保持服务器开启状态,不会退出
		"dev":"webpack --config ./webpack.dev.config.js",
		// 运行后打包退出
		"prod":"webpack --config ./webpack.prod.config.js"
	}

安装html-webpack-plugin插件

	npm install html-webpack-plugin --save-dev

使用目的:之前html中的script标签所引用的还是写死的index.bundle.js文件,为了把它们变成动态的index.html文件,让这个动态生成的index.html文件动态引入我们打包后生成的js文件。

webpack-dev-server

npm install webpack-dev-server --seve-dev

常见配置参数:
--open 自动打开浏览器
--hot 热更新,不在刷新的情况下替换css
--inline 自动刷新
--port:9999 指定端口
--process 显示编译进度

// package.json
"script":{
	"dev":"webpack-dev-server --open --hot --inline --config ./webpack.config.js"
}

ES6的解析

	npm install babel-core babel-loader babel-preset-env babel-plugin-transform-runtime -D

babel-loader:转译器
babel-preset-env:预设,env包括es6,7,8等所有版本

loaders:[
	{
		test:/\.js$/, //处理es6,7,8
		loader:'babel-loader',
		exclude:/node_modules/, //排除node_modules
		options:{
			presets:['env'], //处理关键字
			plugins:['transform-runtime'] //处理函数
		}
	}
]

CommonsChunkPlugin的使用

主要用来提取第三方库和公共模块,避免首屏加载的bundle文件或按需加载的bundle文件提及过大,从而导致加载时间过长。
chunk分类:

  1. entry chunk : 入口文件
  2. children chunk :入口文件以及它的依赖文件通过代码切割出来的chunk
  3. common chunk:通过commonsChunkPlugin创建出来的文件
// webpack.dev.config.js
// 场景:有main1和main2两个js入口文件,并且都有导入commonjs和Vue,打包后的main1和main2的js文件,都存在commonjs,vue和webpack的运行文件模块,加大了入口文件的加载速度,所以需要把第三方库vue,公共文件commonjs和webpack运行文件分离出来。
const webpack = require('webpack');
const packagejson = require('./package.json');
module.exports={
	entry:{
		// 3个入口文件
		"main1":"./src/main1.js",
		"main2":"./src/main2.js",
		"vendor":Object.keys(packagejson.depencies) //获取生产环境依赖的库	
	},
	...
	watch: true, // 监听代码改变视图,需要手动刷新
	plugins:[
		// 第一步为从入口文件中抽离公共的模块,包括第三方库,自定义的公共模块,以及webpack的运行文件,生成vendor.js,"vendor"为自定义的名称
		new webpack.optimize.CommonsChunkPlugin({
			// 第二步是:“runtime”是指从vendor.js文件中抽离出webpack的运行文件,生成runtime.js
			name:['vendor','runtime'],
			filename:'[name].js'// miniChunks属性只有要抽离自定义的公共模块的时候才会用到,不分离则不用写miniChunk属性
			miniChunks: Infinity
			// 只有当入口文件(entry chunks)>= 3 才生效,用在第三方库中分离自定义的公共模块
		});
		// 第三步是抽离出common.js
		new webpack.optimize.CommonsChunkPlugin({
			name:'common', //名称自定义
			filename:'[name].js',
			// 从main1和main2中抽取出commons chunk
			chunks: ['main1','main2']
		})
	]
}

最终生成的dist文件夹中有:
main1.js, main2.js, vendor.js, runtime.js,common.js

ensure异步加载(代码切割)

把js模块导出一个.js文件,使用这个模块的时候,webpack会构造scriptdom元素,加入到document的head对象中即可,由浏览器发其异步请求这个文件。

// commonJS 规范
//A.js
var A = {"data":"HelloA"}
module.exports = A;
//B.js
var B = {"data":"HelloB"}
module.exports = B;
// 场景:在点击aBtn的时候异步加载A.js,再点击bBtn的时候异步加载B.js
// main.js
import Vue from 'vue';
document.getElementById('aBtn').onclick=function(){
	// 异步加载A.js(require是commonJS规范)
	require.ensure([],function(){
		var A = require('./A.js');
	})
}
document.getElementById('bBtn').onClick=function(){
	// 异步加载B.js
	require.ensure([],function(){
		var B = require('./B.js');
	})
}
//webpack.dev.config.js
module.exports={
	entry:{
		// 入口文件
		"main":"./src/main.js",
		// util是自定义的名称,获取package.json文件中包含的依赖
		"util": Object.keys(packagejson.dependencies)
	},
	plugins:[
		// 抽离出公共文件commonjs
		new webpack.optimize.CommonsChunkPlugin({
			name: "common",
			filename:'[name].js'
		}),
		new HtmlWebpackPlugin({
			// 加载哪些入口文件,按顺序加载,公共资源放在前面
			chunks:['common','util','main'],
			template:"./src/index.html", //参照物,模板路径
			inject: true //加载script后,设置放在document的哪个位置(true,head,body,false),其中false为不加载
		})
	]
	
}

package.json文件配置以及修改

	{
	  "name": "webpack-test",
	  "version": "1.0.0",
	  "description": "",
	  "private": true,
	  "scripts": {
	    "test": "echo \"Error: no test specified\" && exit 1",
	    "build": "webpack"
	  },
	  "keywords": [],
	  "author": "",
	  "license": "ISC",
	  "devDependencies": {
	    "html-webpack-plugin": "^3.2.0",
	    "lodash": "^4.17.11",
	    "webpack": "^4.29.6",
	    "webpack-cli": "^3.2.3"
	  }
	}

注意:

  1. 我们还需要调整 package.json 文件,以便确保我们安装包是私有的(private)并且移除 main 入口这可以防止意外发布你的代码。
  2. 在此示例中,<script>标签之间存在隐式依赖关系。index.js 文件执行之前,还依赖于页面中引入的 lodash。之所以说是隐式的是因为 index.js 并未显式声明需要引入 lodash,只是假定推测已经存在一个全局变量 _。
	npm install lodash --save-dev

我的文件目录

文件目录

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值