webpack4 + vue+django

首先想说官网的教程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]"
        }
      }]
      }
    ]
  }
};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容