Skip to content

webpack入门

Oaoafly edited this page Mar 1, 2017 · 1 revision

1.安装webpack

//全局安装
npm install -g webpack
//安装到你的项目目录
npm install --save-dev webpack

这里记得一定要全局安装webpack,不然无法在命令行执行webpack指令

2.准备阶段

npm init

执行后会在根目录生成一个package.json的文件 文件目录结构如下: image

// Greeter.js
module.exports = function() {
	var greet = document.createElement('div');
	greet.textContent = "Hi there and greetings!";
	console.log("test");
	return greet;
};
//main.js 
var greeter = require('./Greeter.js');
document.getElementById('root').appendChild(greeter());
<!--index.html-->
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8">
		<title>Webpack Sample Project</title>
	</head>
	<body>
		<div id='root'>
		</div>
		<script src="bundle.js"></script>
	</body>
</html>
//webpack.config.js
module.exports = {
	//devtool: 'eval-source-map', //用于调试代码
	entry: __dirname + "/app/main.js", //已多次提及的唯一入口文件
	output: {
		path: __dirname + "/public", //打包后的文件存放的地方
		filename: "bundle.js" //打包后输出文件的文件名
	}
}

3.执行命令打包

当我们在根目录下有上面写好完整的webpack.config.js之后,我们可以在命令行执行webpack执行打包,如果成功就会在public文件夹生成一个bundle.js文件 image

当然你还可以在package.json自己定义好一个执行命令来代替这些繁琐的命令,例如

//package.json
{
  "name": "wscat-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "dependencies": {
    "webpack": "^1.14.0"
  },
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack" 
  },
  "author": "",
  "license": "ISC"
}

加上这句之后

"start": "webpack" //配置的地方就是这里啦,相当于把npm的start命令指向webpack命令

你就可以执行npn run start

image

还有注意的是,如果不加下面的代码,在调试代码的时候很可能就找不到行数了

devtool: 'eval-source-map', //用于调试代码

加了之后就会显示未合并之前的文件所在行数 image 未加则显示合并后在bundle.js的行数 image

devtool选项对应的配置结果

  1. source-map:在一个单独的文件中产生一个完整且功能完全的文件。这个文件具有最好的source map,但是它会减慢打包文件的构建速度
  2. cheap-module-source-map:在一个单独的文件中生成一个不带列映射的map,不带列映射提高项目构建速度,但是也使得浏览器开发者工具只能对应到具体的行,不能对应到具体的列(符号),会对调试造成不便
  3. eval-source-map:使用eval打包源文件模块,在同一个文件中生成干净的完整的source map。这个选项可以在不影响构建速度的前提下生成完整的sourcemap,但是对打包后输出的JS文件的执行具有性能和安全的隐患。不过在开发阶段这是一个非常好的选项,但是在生产阶段一定不要用这个选项
  4. cheap-module-eval-source-map:这是在打包文件时最快的生成source map的方法,生成的Source Map 会和打包后的JavaScript文件同行显示,没有列映射,和eval-source-map选项具有相似的缺点

上述选项由上到下打包速度越来越快,不过同时也具有越来越多的负面作用,较快的构建速度的后果就是对打包后的文件的的执行有一定影响

4.配置服务器

npm install -g webpack-dev-server
npm install --save-dev webpack-dev-server

webpack.config.js文件添加配置项

module.exports = {
	devtool: 'eval-source-map', //用于调试代码
	entry: __dirname + "/app/main.js", //已多次提及的唯一入口文件
	output: {
		path: __dirname + "/public", //打包后的文件存放的地方
		filename: "bundle.js" //打包后输出文件的文件名
	},
	devServer: {
		contentBase: "./public", //本地服务器所加载的页面所在的目录
		historyApiFallback: true, //不跳转
                //port 设置默认监听端口,如果省略,默认为”8080“
		inline: true //实时刷新
	}
}

然后在命令行执行webpack-dev-server image 在浏览器打开http://localhost:8080/ 就会显示静态页面,如果改动文件,浏览器还会热更新

devserver配置选项和功能描述

  1. contentBase:默认webpack-dev-server会为根文件夹提供本地服务器,如果想为另外一个目录下的文件提供本地服务器,应该在这里设置其所在目录(本例设置到“public"目录)
  2. port:设置默认监听端口,如果省略,默认为”8080“
  3. inline:设置为true,当源文件改变时会自动刷新页面
  4. colors:设置为true,使终端输出的文件为彩色的
  5. historyApiFallback:在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html

5.css-loader

webpack提供两个工具处理样式表,css-loader 和 style-loader,二者处理的任务不同 css-loader使你能够使用类似@import和url(...)的方法实现require()的功能 style-loader将所有的计算后的样式加入页面中,二者组合在一起使你能够把样式表嵌入webpack打包后的JS文件中

npm install --save-dev style-loader css-loader

然后我们就可以在webpack.config.js文件里面添加这个loader的配置项

module.exports = {
	devtool: 'eval-source-map', //用于调试代码
	entry: __dirname + "/app/main.js", //已多次提及的唯一入口文件
	output: {
		path: __dirname + "/public", //打包后的文件存放的地方
		filename: "bundle.js" //打包后输出文件的文件名
	},
	module: {
		loaders: [{
			test: /\.css$/,
			loader: 'style-loader!css-loader'
		}, ]
	},
	devServer: {
		contentBase: "./public", //本地服务器所加载的页面所在的目录
		historyApiFallback: true, //不跳转
		inline: true //实时刷新
	}
}

"-loader"其实是可以省略不写的,多个loader之间用“!”连接起来

/*main.css*/
p{
	color: red;
}
<!--index.html-->
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8">
		<title>Webpack Sample Project</title>
	</head>
	<body>
		<div id='root'>
		</div>
		<p>hello</p>
		<script src="bundle.js"></script>
	</body>
</html>

此时我们就可以在main.js里面直接引进main.css,那所有样式都会打包成js,在项目运行的时候会转化为**<style>**标签自动引进原页面中

webpack只有单一的入口,其它的模块需要通过import,require,url等导入相关位置,为了让webpack能找到”main.css“文件,我们把它导入”main.js “中

//main.js 
var greeter = require('./Greeter.js');
require('./main.css');
document.getElementById('root').appendChild(greeter());

6.url-loader

还可以对图片进行打包,用这个还要先安装

module.exports = {
	devtool: 'eval-source-map', //用于调试代码
	entry: __dirname + "/app/main.js", //已多次提及的唯一入口文件
	output: {
		path: __dirname + "/public", //打包后的文件存放的地方
		filename: "bundle.js" //打包后输出文件的文件名
	},
	module: {
		loaders: [{
			test: /\.css$/,
			loader: 'style-loader!css-loader'
		}, {
			test: /\.(png|jpg)$/,
			loader: 'url-loader?limit=8192'
		}]
	},
	devServer: {
		contentBase: "./public", //本地服务器所加载的页面所在的目录
		historyApiFallback: true, //不跳转
		inline: true //实时刷新
	}
}

配置信息的参数“?limit=8192”表示将所有小于8kb的图片都转为base64形式(其实应该说超过8kb的才使用 url-loader 来映射到文件,否则转为data url形式)

//main.js 
var img1 = document.createElement("img");
img1.src = require("./logo.png");
document.body.appendChild(img1);

7.babel-loader

安装babel-loader,现在我们就可以放心的用ES6的语法了

npm install --save-dev babel-loader
// Greeter.js
module.exports = function() {
	var greet = document.createElement('div');
	greet.textContent = "Hi there and greetings!";
	console.log("test2");
	return greet;
};

可以把上面的代码用ES6改写成下面的格式

// Greeter.js
export default function f(){
	var greet = document.createElement('div');
	greet.textContent = "Hi there and greetings!";
	console.log("test2");
	return greet;
};
var greeter = require('./Greeter.js'); //ES5
import greeter from './Greeter.js'; //ES6

exportexport default均可用于导出常量、函数、文件、模块等,你可以在其它文件或模块中通过import+(常量 | 函数 | 文件 | 模块)名的方式,将其导入,以便能够对其进行使用,但在一个文件或模块中,export、import可以有多个,export default仅有一个

所以上面是只导出一个函数的情况,如果导出多个可以用下面这种方式

// test.js
export const str = 'hello world'
export function f(a){
    return a+1
}
import {
	str,
	f
} from './test.js';

8.vue-loader

vue-loader能够把我们的组件.vue文件转化为js加载到我们项目中

<!-- app.vue-->
<template>
	<div>{{msg}}</div>
</template>
<script>
	export default {
		data() {
			return {
				msg: 'Hello from vue-loader!'
			}
		},
	}
</script>
<style>
	div {
		color: red;
	}
</style>

这里面要注意的是vue2开始要用render: (createElement) => createElement(App)来注册组件,components在vue1才能使用了,当然在组件.vue文件里面注册组件还是可以用components, 还有需要注意的是vue2之后不能在el为body和html节点上添加组件,所以我这里改成el: '#app'

var Vue = require('vue')
var App = require('./app.vue')
//import App from './app.vue'
new Vue({
	el: '#app',
	render: (createElement) => createElement(App)
	/*components: {
		app: App
	}*/
})

webpack.config.js要添加resolve和vue-loader

//webpack.config.js
module.exports = {
	devtool: 'eval-source-map', //用于调试代码
	entry: __dirname + "/app/abc.js", //已多次提及的唯一入口文件
	output: {
		path: __dirname + "/public", //打包后的文件存放的地方
		filename: "bundle.js" //打包后输出文件的文件名
	},
	module: {
		loaders: [{
			test: /\.css$/,
			loader: 'style-loader!css-loader'
		}, {
			test: /\.(png|jpg)$/,
			loader: 'url-loader?limit=8192'
		}, {
			test: /\.js$/,
			exclude: /node_modules/,
			loader: "babel-loader"
		}, {
			test: /\.vue$/,
			loader: 'vue-loader'
		}]
	},
	devServer: {
		contentBase: "./public", //本地服务器所加载的页面所在的目录
		historyApiFallback: true, //不跳转
		inline: true //实时刷新
	},
	resolve: {
		alias: {
			vue: 'vue/dist/vue.js'
		}
	}
}