美文网首页
webpack4 + vue+django

webpack4 + vue+django

作者: 黑夜的眸 | 来源:发表于2018-09-03 13:56 被阅读0次

    首先想说官网的教程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]"
            }
          }]
          }
        ]
      }
    };
    

    相关文章

      网友评论

          本文标题:webpack4 + vue+django

          本文链接:https://www.haomeiwen.com/subject/vwklwftx.html