webpack安装
- 安装最新版的Node.js和NPM
- 创建一个目录,使用NPM初始化配置:
npm init
; 完成后会在demo目录生成一个package.json - 在本地局部安装webpack:
npm install webpack webpack-cli --save-dev
- 安装webpack-dev-server:
npm install webpack-dev-server --save-dev
webpack配置
- 在目录DEMO下创建一个js文件,文件名为webpack.config.js,并初始化其内容:
var config = {
};
module.exports = config;
- 在package.json的scripts里增加一个快速启动webpack-dev-server服务的脚本:
{
//...
“scripts":{
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --open --config webpack.config.js"
},
//...
}
注意网页打开的默认地址是127.0.0.1:8080
ip和端口都可以配置,见下面:
“webpack-dev-server --host 172.172.172.1 --port 8888 --open --config webpack.config.js”
- 在demo目录下新建一个空的main.js作为入口的文件,然后在webpack.config.js中进行入口和输出的配置:
var path = require('path');
var config = {
entry: {
main: './main'
},
output: {
path: path.join(_dirname, './dist'),
publicPath: '/dist/',
filename: 'main.js'
}
}
module.exports = config;
说明:
webpack配置中最重要的是入口(Entry)和出口(Output)。
入口是告诉webpack从哪里开始寻找依赖,出口是配置编译后的文件存储位置和文件名
- 在demo目录下,新建一个index.html作为SPA的入口
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>webpack App</title>
</head>
<body>
<div id="app">
Hello World.
</div>
<script type="text/javascript" src="/dist/main.js"></script>
</body>
<html>
完善webpack配置
在webpack里,每个文件都是一个模块,对于不同的模块,需要用不同的加载器(Loaders)来处理。通过安装不同的加在其可以对各种后缀名的文件进行处理。如css样式,就要用到style-loader和css-loader。通过NPM来安装:
npm install css-loader --save-dev
npm install style-loader --save-dev
安装完后,在webpack.config.js文件里配置Loader,增加对.css文件的处理
var config = {
//...
module:{
rules:{
test: /\.css$/,
use:[
'style-loader',
'css-loader'
]
}
}
};
module.exports = config;
在module对象的rules属性中可以指定loaders,每一个loader都必须包含test和use。这段配置的意思是在编译过程中遇到require()和import语句导入仪个后缀名为.css文件时,先用css-loader转换,再通过style-loader转换,然后继续打包。
注意:use选项可以是数组,如果是数组,它的编译顺序是从后往前。
在demo目录下新建一个style.css的文件,并在main.js中导入
/* style.css*/
#app{
font-size: 24px;
color: #f50;
}
//main.js
import './style.css'
document.getElementById('app').innerHTML = 'Hello webpack.';
重新执行npm run dev命令,页面样式会发生改变。
插件
在上面的例子中,这样把样式一个一个放在js会很不方便,可以使用插件来将css都提取出来,生成一个main.css文件,最终在index.html里通过的形式来加载,这里使用到的插件是extract-text-webpack-plugin
通过NPM来安装:
npm install extract-text-webpack-plugin --save-dev
然后在配置文件中导入插件,并改写loader的配置
//导入插件
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var config = {
//...
module:{
rules:{
test: /\.css$/,
use:ExtractTextPlugin.extract({
use: 'css-loader',
fallback:'style-loader'
})
}
},
plugins: [
// 重命名提取后的css文件
new ExtractTextPlugin("main.css")
]
};
module.exports = config;
//index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>webpack App</title>
<link rel="stylesheet" type="text/css" href="/dist/main.css">
</head>
<body>
<div id="app">
Hello World.
</div>
<script type="text/javascript" src="/dist/main.js"></script>
</body>
<html>
webpack看似复杂,但只要搞清入口,出口,加载器和插件这4个概念即可
单文件组件与vue-loader
.vue单文件组件就是一个后缀名为.vue的文件,在webpack中使用vue-loader就可以对.vue格式的文件进行处理。
一般.vue文件一般有3个部分,即<template>, <script>和<style>
<template>
之间的代码是改组件的模板HTML
<style>
是CSS样式,使用scoped,表示当前CSS只在这个组件有效<style scoped>
;<style>
还可以结合CSS预编译一起使用,比如Less可以写成<style lang="less">
使用.vue文件需要先安装vue-loader, vue-style-loader等加载器并做配置,还需要安装babel和babel-loader等加载器,使用npm逐个安装以下依赖
npm install --save vue
npm install --save-dev vue-loader
npm install --save-dev vue-style-loader
npm install --save-dev vue-template-compiler
npm install --save-dev vue-hot-reload-api
npm install --save-dev babel
npm install --save-dev babel-loader
npm install --save-dev babel-core
npm install --save-dev babel-plugin-transform-runtime
npm install --save-dev babel-preset-es2015
npm install --save-dev babel-runtime
修改配置文件webpack.config.js来支持对.vue文件及ES6的解析
var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var config = {
entry: {
main: './main'
},
output: {
path: path.join(__dirname, './dist'),
publicPath: '/dist/',
filename: 'main.js'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
css: ExtractTextPlugin.extract({
use: 'css-loader',
fallback: 'vue-style-loader'
})
}
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: 'css-loader',
fallback: 'style-loader'
})
},
{
test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
loader: 'url-loader?limit=1024'
}
]
},
plugins: [
new ExtractTextPlugin("main.css")
]
};
module.exports = config;
在demo目录下新建一个名为.babelrc的文件,并写入babel的配置,webpack会依赖此配置文件来使用编译ES6代码
{
"presets": ["es2015"],
"plugins": ["transform-runtime"],
"comments": false
}
配好这些就可以使用.vue文件,每个.vue文件就代表一个组件
在demo目录下新建一个app.vue的文件并写入以下内容
<template>
<div>
<v-title title="Vue组件化"></v-title>
<v-button @click="handleClick">点击按钮</v-button>
<p>
<img src="./images/image.png" style="width: 200px;">
</p>
</div>
</template>
<script>
import vTitle from './title.vue';
import vButton from './button.vue';
export default {
components: {
vTitle,
vButton
},
methods: {
handleClick (e) {
console.log(e);
}
}
}
</script>
写好组件,就可以在入口main.js中使用了,main.js的内容如下:
import Vue from 'vue';
import App from './app.vue';
new Vue({
el: '#app',
render: h => {
return h(App)
}
});
在app.vue文件导入其他.vue文件,使用import语句,如:
import vTitle from './title.vue'
打包上线
单页面富应用技术,即只有一个html文件,其余都是静态资源,实际部署时,一般将html挂在后端程序下,有后端路由去渲染,将所有的静态资源单独部署到cdn,这样来实现前后端完全分离
打包会用到下面两个依赖,使用NPM安装
//用来合并两个webpack的配置文件
npm install --save-dev webpack-merge
//用来生成html文件
npm install --save-dev html-webpack-plugin
编译打包,直接执行webpack命令就可以。
在package.json中,再加入一个build的快捷脚本用来打包
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --open --config webpack.config.js",
"build": "webpack --progress --hide-modules --config webpack.prod.config.js"
},
再看下webpack.prod.config.js的代码
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var merge = require('webpack-merge');
var webpackBaseConfig = require('./webpack.config.js');
// 清空基本配置的插件列表
webpackBaseConfig.plugins = [];
module.exports = merge(webpackBaseConfig, {
output: {
publicPath: '/dist/',
// 将入口文件重命名为带有 20 位 hash 值的唯一文件
filename: '[name].[hash].js'
},
plugins: [
new ExtractTextPlugin({
// 提取 css,并重命名为带有 20 位 hash 值的唯一文件
filename: '[name].[hash].css',
allChunks: true
}),
// 定义当前 node 环境为生产环境
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
// 压缩 js
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
// 提取模板,并保存入口 html 文件
new HtmlWebpackPlugin({
filename: '../index_prod.html',
template: './index.ejs',
inject: false
})
]
});
在index.ejs动态设置静态资源的路径和文件名:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Webpack App</title>
<link rel="stylesheet" href="<%= htmlWebpackPlugin.files.css[0] %>">
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="<%= htmlWebpackPlugin.files.js[0] %>"></script>
</body>
</html>