首先想说官网的教程webpack4很赞,每一步都讲解的很到位,但是如果和vue搭配起来,还是有很多细节新手不注意的话就会出问题。vue-cli3.0虽然帮助vue新手不用关注过多环境配置,快速上手开展项目,但后期run npm build建立生产模式的时候, 遇到很多坑,比如js,css加载报404错误,页面空白等等。官网对个性化配置又讲得不清楚,没有对vue.config.js这样一个重要的文件做详细说明,用vue-cli构建的初始项目里并不会有这样的配置文件。
所以,还是转而用webpack4,vue-cli3.0是基于webpack3,目前是不支持webpack4的许多新特性的,花些时间学习webpack4是很有价值的。本文旨在为自己搭建过程中遇到的问题以及配置做一个记录说明,以便可以根据此文快速搭建。
一个简单的webpack的项目目录应当是这样的结构:
webpack-demo
|- package.json 项目依赖描述文件
|- webpack.config.js 核心配置文件
|- /dist 打包后输出文件目录
|- index.js 输出文件js
|- index.html 输出文件html
|- /src 源程序文件目录
|- APP.vue vue主文件
|- main.js 项目主文件
|- template.html 生成index.html的模板[vue得力助手]
|- /node_modules 依赖包文件目录
- src 里以后存放vue项目
- dist 可以不用建,但必须在webpack.config.js里详细配置
- webpack.config.js 如果要两种模式下分别使用不同配置,则需要两个文件,例如:prod.config.js和webpack.config.js
- package.json 里
webpack --config
设置调用哪个配置文件,不设置则会默认寻找webpack.config.js。
开始项目前,首先确保你有npm工具,通过命令
mkdir webpack-demo && cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev
会在你的本地创建webpack-demo并安装webpack-cli及webpack,npm install --save的意思是会将你安装的记录保存在package.json,-dev意思是安装在开发环境
package.json
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"watch": "webpack --watch",
"dev": "webpack-dev-server --open",
"build": "webpack --config prod.config.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.24.1",
"babel-loader": "^7.0.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"babel-preset-stage-3": "^6.24.1",
"babel-register": "^6.24.1",
"css-loader": "^1.0.0",
"file-loader": "^2.0.0",
"html-webpack-plugin": "^3.2.0",
"less": "^3.8.1",
"less-loader": "^4.1.0",
"style-loader": "^0.23.0",
"vue-loader": "^15.4.1",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.5.17",
"webpack": "^4.17.1",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.6"
},
"dependencies": {
"axios": "^0.18.0",
"iview": "^3.0.1",
"jquery": "^3.3.1",
"lodash": "^4.17.10",
"vue": "^2.5.17",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"
}
}
- 该文件是通过
npm init -y
生成的基础文件 - devDependencies是开发环境所需的依赖包,dependencies是生产环境所需的依赖包
- 如果有这个文件,运行
npm install
就可以按照这里面的配置及版本信息生成node_modules目录下的依赖包文件,该文件列出了vue基本所需,项目后期不够可再自行安装。
在这里强调生产环境和开发环境用两种配置的重要性,举一个简单的例子:如果将三个源文件(a.js,b.js和c.js)捆绑到一个bundle(bundle.js)中,并且其中一个源文件包含错误,则堆栈跟踪将简单地指向bundle.js。这并不总是有用,因为您可能想要确切地知道错误来自哪个源文件。
devtool: 'inline-source-map'
帮助开发者在开发时 能准确跟踪错误位置,但是速度会牺牲。另一个是SourceMapDevToolPlugin,提供的options可以有更多配置,如果直接写webpack.SourceMapDevToolPlugin({})等效于inline-source-map
plugins: [
devtool: false
new webpack.SourceMapDevToolPlugin(options);
]
prod.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
mode:'production',
entry: {
myweb: './src/main.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: "static/myweb/[name].entry.js",
chunkFilename: "static/myweb/[name].min.js",
publicPath: '/'
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'template.html',
inject: true
}),
new webpack.HotModuleReplacementPlugin(),
new VueLoaderPlugin()
],
optimization: {
minimizer: [
new UglifyJsPlugin()
]
},
resolve: {
// require时省略的扩展名
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.common.js'
}
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.less$/,
use: [{
loader: 'style-loader'
}, {
loader: 'css-loader'
}, {
loader: 'less-loader', options: {
strictMath: true,
noIeCompat: true
}
}]
},
{
test: /\.vue$/,
use: ['vue-loader']
},
{
test: /\.js$/,
use: [{
loader:'babel-loader'
}
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [{
loader:'file-loader',
options: {
outputPath:"static/myweb/",
name:"[name].[ext]"
}
}]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [{
loader:'file-loader',
options: {
outputPath:"static/myweb/",
name:"[name].[ext]"
}
}]
}
]
}
};
- entry为项目的入口,默认为'./src',它也可以这样配置成多文件入口
entry: ["./app/entry1", "./app/entry2"],
entry: { a: "./app/entry-a", b: ["./app/entry-b1", "./app/entry-b2"] },
这里配置成了entry: {
myweb: './src/main.js'
}, - output 为输出出口
-path: 一般配置成path.resolve(__dirname, "dist")就好
-filename:[name].entry.js
这里允许根据入口点动态生成包,一般在多入口文件中有用,name与entry配置的myweb
一致,所以会在dist/static/myweb下输出一个myweb.entry.js文件,这里把它放在static/myweb里面,以便移入后端项目时不混乱,把myweb文件夹拷贝至另一个项目的static目录下,相互依赖关系则可不变。
-publicPath:这里配置成了'/'
注意:由于前端vue 用webpack build生成项目后,放到后端django里面,一般是会把index.html放到项目根目录的templates文件夹,把其他静态文件放到根目录的static文件夹,由于依赖路径变了,经常会出现404错误(webpack 是依赖相对路径,django是依赖绝对路径)。用url访问静态文件,你可以把dist想象成localhost,其实路径是这样的:
src = publicPath + filename = "/static/myweb/myweb.entry.js",因此
url= "127.0.0.1:8000/static/myweb/myweb.entry.js"
在django的setting里有这样的配置:
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
那么127.0.0.1:8000/static/ => BASE_DIR/static
所以最终访问地址:BASE_DIR/static/myweb/myweb.entry.js,这正符合我们的需求
-
module:配置对不同类型文件使用的装载机,注意图片与字体额外配置了options选项,outputPath可以自定义输出的目录,name自定义输出的名字,这样也是避免在后期放入后端时混乱,这里官网觉得不重要,没仔细讲,查了文档才知道
-
HtmlWebpackPlugin 很关键的一个参数,官网在入门指南里讲得不是很明确,只留了一个详细文档的链接,要点进去看才知道
# webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'template.html',
inject: true
})
]
}
-filename 配置成index.html会在dist下生产一个文件名为index.html这样的文件
-template:生产一个文件名为index.html所依据的模板,直接写template.html
它是会在根目录下寻找该文件的,在这里面一定注意配置<div id="app"><div>
, webpack自动生成的是不会帮你加上的,但其他依赖的 js会自动帮你加上。
-inject:
true: js放入<body></body>
false: js放入<head></head>
# template.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>首页</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
#自动生成的intex.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>首页</title>
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="/static/myweb/myweb.entry.js"></script></body>
</html>
-
clean-webpack-plugin :在每次构建/dist之前清理文件夹
-
devtool: 前面已讲,不再详述,应避免在生产配置中使用它
-
devServer: {
contentBase: './dist'
//hot: true
},提供了一个简单的Web服务器和使用实时重新加载的能力,避免在生产配置中使用它,这告诉webpack-dev-server我们从dist目录中提供文件localhost:8080。
*hot :热加载, 点这里, 如果不在项目src中写如何加载是没有意义的。 -
resolve: 帮助src源文件中require时省略扩展名
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
mode:'production',
entry: {
myweb: './src/main.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: "[name].entry.js",
chunkFilename: "[name].min.js",
publicPath: ''
},
devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
hot: false
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'template.html',
inject: true
}),
new VueLoaderPlugin()
],
resolve: {
// require时省略的扩展名
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.common.js'
}
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.less$/,
use: [{
loader: 'style-loader'
}, {
loader: 'css-loader'
}, {
loader: 'less-loader', options: {
strictMath: true,
noIeCompat: true
}
}]
},
{
test: /\.vue$/,
use: ['vue-loader']
},
{
test: /\.js$/,
use: [{
loader:'babel-loader'
}
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [{
loader:'file-loader',
options: {
name:"[name].[ext]"
}
}]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [{
loader:'file-loader',
options: {
name:"[name].[ext]"
}
}]
}
]
}
};
网友评论