一直都以为SSR是一个挺麻烦的事情,牵扯的知识范围还挺大的,尤为是用vue-cli 工具,屏蔽了许多配置的细节。
但在使用SSR,不用Nuxt.js 的时候来作SSR,仍是挺难上手的,索性好好捋一遍这方面的相关知识,总结成了一个系列的文章。做为 SSR 文档的一个补充,但愿对你们有所帮助。javascript
这篇文章的主要目的解读一个简单的 vue-webpack 如何搭建和每个插件的做用。完成一个 client-only的 vue-webpack 开发环境,具有如下的功能:css
对这相关配置已经很是了解了的同窗能够直接关闭了。html
从这一节开始会贴出一步一步实现的代码,尽可能还原整个配置的细节。前端
$ mkdir simple-webpack && cd simple-webpack
$ npm init复制代码
而后按照下面的目录结构新建文件。vue
.
├── index.html
├── package.json
├── src
│ ├── App.vue
│ ├── app.js
│ └── assets
└── webpack.config.js复制代码
须要安装 webpack 须要的依赖有:java
依次安装时,把安装依赖保存到package.json,以便下次在不一样的环境下使用时,能快速的安装依赖。node
index.htmlwebpack
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>simple - webpack</title>
</head>
<body>
<div id="app"></div>
<script src="/dist/build.js"></script>
</body>
</html>复制代码
App.vuegit
<template>
<div class="demo">
<h1>Simple-webpack demo</h1>
<p>这是一个简单的 Vue demo</p>
</div>
</template>
<script> </script>
<style> </style>复制代码
app.jsgithub
import Vue from 'vue'
import App from './App.vue'
new Vue({
el: '#app',
render: h => h(App)
})复制代码
先写好咱们的入口文件和输出文件的地址和打包后的文件名。
const webpack = require('webpack')
const path = require('path')
module.exports = {
entry: './src/app.js',
output: {
path: path.resolve(__dirname, './dist/'),
filename: 'build.js'
}
}复制代码
添加 vue-loader
module.exports = {
entry: './src/app.js',
output: {
path: path.resolve(__dirname, './dist/'),
publicPath: '/dist/',
filename: 'build.js'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: ''
}
]
}
}复制代码
此时运行 webpack
打包就能够打包成一个可用的程序了,你们能够自行打包后将文件放在静态服务器中运行。
完成这个基本的打包,用到的webpack loader 和包有:
这个包 npm 官网上都有详细的介绍,这里就不赘述了,你们能够自行去看各个loader 在上面的打包过程当中完成什么样工做。
为了让咱们编写的代码能在低版本的浏览器中使用,咱们添加 babel-loader,在打包的时候将文件中的 ES6 语法转成 .bablerc 中配置的版本。
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: ''
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [path.resolve(__dirname, './src')]
}
]
}复制代码
在目录下建立 .babelrc,配置内容以下:
{
"presets": [
["env", { "modules": false }]
]
}复制代码
而后须要安装一个 babel 插件,babel-preset-env, 关于这个插件的做用具体参见 babel-preset-env
: a preset that configures Babel for you
给 App.vue 中添加图片:
<template>
<div class="demo">
<h1>Simple-webpack demo</h1>
<p>这是一个简单的 Vue demo</p>
<img src="./assets/logo.png" alt="">
</div>
</template>复制代码
由于添加了图片,再运行 webpack 打包的时候,webpack 会报错,由于没有对应的 loader 去加载这些二进制文件。
添加 file-loader:
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: ''
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [path.resolve(__dirname, './src')]
},
{
test: /\.(png|jpg|svg|git)$/,
loader: 'file-loader',
include: [path.resolve(__dirname, './src/assets')]
}
]
},复制代码
目前咱们在单文件组件中,能够使用 css,可是还不能使用 sass,我再添加一个对应的 sass-loader 来处理 sass 文件,由于 css/sass 是 vue-loader 在作代码分割的时候分割出来的文本段,咱们只须要在 vue-loader 的 options 中添加对应的配置。
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
'scss': 'vue-style-loader!css-loader!sass-loader',
'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax'
}
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [path.resolve(__dirname, './src')]
},
{
test: /\.(png|jpg|svg|git)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},复制代码
到目前为止,一个具有打包编译 Vue 项目的 webpack 环境配置已经写好了。接下来咱们添加两个比较重要的辅助工具 devServer 和 hot replace。
添加 Dev Server 的方式的方式有两种:
两种的使用方式和配置能够看这篇官网介绍 开发。这里咱们选用一种比较简单的方式,直接使用 webpack-dev-server。
先安装 npm install -S webpack-dev-server
,再修改 package.json 添加 npm script,代码以下:
"scripts": {
"test": "",
"dev": "webpack-dev-server --open"
}复制代码
open 参数表明服务启动后会自动在浏览器中打开页面。而后再打开 webpack.config.js 文件,添加 devServer 的相关配置。除了以上的配置还能修改 host 和 port,这里咱们使用默认就行。添加 hot replace 也是很是简单的,webpack 自带了这一个 plugin,具体使用方法能够看 模块热替换,新增的配置代码以下:
module: {
//...
},
devServer: {
historyApiFallback: true,
hot: true,
noInfo: false,
overlay: true
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]复制代码
process
是 node 中的一个模块,咱们能够用它的 env 变量来区分 shell 的环境变量。这样咱们就能够经过 npm run dev
和 npm run build
来区分咱们是开发仍是生产构建。
先修改两个 npm script 来区分 shell 环境变量,这里咱们借助 cross-env npm 模块实现自定义的环境变量。
"scripts": {
"test": "",
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack"
}复制代码
// webpack.config.js
module.exports = {
//...
}
console.log(process.env.NODE_ENV)
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
])
}复制代码
在 production 环境中添加了两个插件,优化打包的代码和压缩 JS 代码。第一个插件 DefinePlugin 是为前端代码提供与 webpack 一致的环境变量,便于咱们在业务代码中区分不一样的环境,Vue 框架中也要根据这个环境变量来切分开发环境和生产环境。
咱们再稍微整理一下配置,一个简单 client-only 的 webpack 的配置就写好了。
const webpack = require('webpack')
const path = require('path')
module.exports = {
entry: './src/app.js',
output: {
path: path.resolve(__dirname, './dist/'),
publicPath: '/dist/',
filename: 'build.js'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
'scss': 'vue-style-loader!css-loader!sass-loader',
'sass': 'vue-style-loader!css-loader!sass-loader'
}
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [path.resolve(__dirname, './src')]
},
{
test: /\.(png|jpg|svg|git)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
}
}
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
])
} else {
module.exports.devtool = '#eval-source-map'
module.exports.devServer = {
historyApiFallback: true,
hot: true,
noInfo: false,
overlay: true
}
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.HotModuleReplacementPlugin()
])
}复制代码
本文只是梳理打造一个简单配置的过程,为后面的 SSR 配置做为基础。webpack 的配置项很是多,而 vue-cli 中提供的 webpack 配置远没有那么简单。更进阶的方式能够阅读参考中文章。