vue异步组件前端的工程化工具--webpack

关于前端的工程化工具

grunt
  • 资源打包
  • 单元测试
gulp
  • 流式操作工具
  • 资源打包

webpack 【 主流 】

学习vue的过程肯定会接触到vue的单文件组件,进而接触到vue-cli(vue工程构建的脚手架工具),但是vue-cli创建的工程对初学者很不友好,vue init webpack-simple project-name创建的项目又太过简单和片面。

接下来我们从初始化到写配置再到添加loader和插件逐步构建一个可用的vue工程化环境,让初学者亲自搭建vue-cli之余还了解到webpack常用的一些配置项。

  • 资源打包工具, 比如 js文件打包压缩 , img 打包压缩 。。。
  • 可以自动解决模块化依赖问题
  • es6模块化

创建工程

前提你已经安装了node、npm环境

mkdir project-vue
cd project-vue

npm init
//初始化设置都按enter默认就好,或者按你需要改

安装webpack到项目中

npm install --save-dev webpack
//啰嗦一下淘宝镜像设置
npm install -g cnpm –registry=https://registry.npm.taobao.org

创建webpack配置文件

webpack在运行时候会找到启用webpack命令目录下的webpack.config.js,所以要创建该文件到项目根目录下。

//webpack.config.jsconst path = require('path')
module.exports ={
    entry:'./src/main.js',
    output:{
        path:path.resolve(__dirname,'dist'),
        filename:"js/[name].js"
    }
}

以上是最简单的模板,设置了入口文件(entry)和出口地址(output),这些有一点webpack基础的都知道,不了解的先去入门一下webpack的基础配置。而path函数则是node自带的路径相关的中间件,基本上整个项目就用到这样一个node的中间件,path就是用来做路径拼接返回一个路径字符串,可以简要看一下path。同时还要创建index.html和main.js文件,项目目录结构如下:
项目结构
index.html

<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>vue demo</title></head><body>
    <div id="app">
    </div>
    <script src="./dist/js/main.js"></script></body></html>

main.js里面随便写点js就行

运行

webpack

这里有一份npm script的介绍,不用谢

npm run build

根目录下会多出一个dist文件夹里面放了打包好的文件。

引入一系列的依赖和loader

vue工程当然要安装vue依赖啦

npm install --save vue

vue-loader是必须的,vue-template-compiler是vue-loader必须的依赖

npm install --save-dev vue-loader vue-template-compiler

写现代的项目怎么可能不用到es6以上,来个es编译器loader

npm install --save-dev babel-core babel-loader

再来个css的加载器和转换器,style-loader会把css转成js,再贴到html的style标签上的哦~

npm install --save-dev css-loader style-loader

还有图片文件和字体文件的加载器,url-loader依赖于file-loader所以都要安装,url-loader会把小于限制的文件改成base64格式直接传入src里面,可以降低网络请求次数。而file-loader会自动帮我们添加文件名规则而且url地址一起跟着改变。

npm install --save-dev file-loader url-loader

以上的loader的配置下面开始简要讲解

loader配置项

每一种loader都对应着一种文件,我们匹配项目种的文件添加loader。

const path = require('path')
const webpack = require('webpack')

module.exports = {
    entry:{
        app:'./src/main.js',
    },
    output:{
        path:path.resolve(__dirname,'./dist'),
        filename:"js/[name].js",
    },
    module:{
        rules:[
            {
                test:/\.js$/, //用正则匹配文件,用require或者import引入的都会匹配到
                loader:"babel-loader", //加载器名,就是上一步安装的loader
                exclude:/node_modules/ //排除node_modules目录,我们不加载node模块中的js哦~
            },
            {
                test:/\.css$/,
                use:[
                    'style-loader',
                    'css-loader',
                    // 'postcss-loader'
                ]
                
                //依次使用以上loader加载css文件,postcss-loader可以暂时不加,后面再深入修改webpack配置的时候再说用处
                //
                //也可以写成这样 loader:"style-loader!css-loader!postcss-loader"
            },
            {
                test:/\.(png|jpe?j|gif|svg)(\?.*)?$/,
                loader:'url-loader',
                options:{
                    limit:10000,
                    name:'img/[name].[ext]?[hash]'
                }
                //图片文件大小小于limit的数值,就会被改写成base64直接填入url里面,
                //不然会输出到dist/img目录下,[name]原文件名,[ext]原后缀,[hash]在url上加上一点哈希值避免缓存。
            },
            {
                test:/\.(woff2?|eot|ttf|otf)(\?.*)?$/,
                loader:"url-loader",
                options:{
                    limit:10000,
                    name:'fonts/[name].[ext]?[hash]'
                }
                //和上面一致
            },
            {
                test:/\.vue$/,
                loader:'vue-loader'
                //这一个loader当然是vue项目必须的加载器啦,不加其他规则的话,
                //简单的这样引入就可以了,vue-loader会把vue单文件直接转成js。
            },
        ]
    },
    resolve:{
        //引入路径是不用写对应的后缀名
        extensions: ['.js', '.vue', '.json'],
        //缩写扩展
        alias:{
            //正在使用的是vue的运行时版本,而此版本中的编译器时不可用的,我们需要把它切换成运行时 + 编译的版本
            'vue$':'vue/dist/vue.esm.js',// 'vue/dist/vue.common.js' for webpack 1
            //用@直接指引到src目录下,如:'./src/main'可以写成、'@/main'
            '@': path.resolve(__dirname,'./src'),
        }
    },
}

开始使用.vue

main.js改成如下

import Vue from 'vue'import './styles/main.css'import App from './app.vue'

new Vue({
  el:"#app",
  template:'<App/>',
  components:{App}
})

新建一个app.vue文件


<template>
    <div id="app">
        <img src="./images/logo.png" alt="logo" />
        <span>{{msg}}</span>
        <p class="test">test text</p>
    </div></template><script>import Vue from 'vue'
    export default {
        name:'app',
        data(){
            return {
                msg:"hello vue !!"
            }
        },
    }
</script><style >
    .test{
        color:#020202
    }
</style><style lang="less"><!--我好像还没说引入less哦,下面说-->
    #app{
        img{width:100px;}
    }
</style>

别忘了弄张图片,写个main.css哦

/*main.css*/
@import './reset.css';
#app{
    color:red;
}

用less或者sass

你可以在项目中用less或者sass,相对的就要安装less-loader和sass-loader

npm install --save-dev less-loader
npm install --save-dev sass-loader

如果没有在全局安装less或sass编译器的话还有安装一下,执行上面loader安装之前先安装less或sass

安装到本项目中
npm install --save-dev less
安装到全局中
npm install --g less

以less-loader为例,修改webpack.config.js

{
    test:/\.less$/,
    use:[
        'vue-style-loader'
        'css-loader',
        'less-loader'
    ]
},
{
    test:/\.vue$/,
    loader:'vue-loader',
    options:{
        loaders:{
            'less':[//lang属性对应的名称
                'vue-style-loader'//首先给vue的样式loader过滤一遍
                'css-loader',//css-loader,把css转js
                'less-loader'//用less编译
            ]
        }
    }
}

使用vue单文件组件的时候给lang属性添加标识就可以了,less后缀的文件也会一起进行编译

<style lang="less">
    #app{
        img{width:100px;}
    }
</style>

sass类似,但sass带有两种语法规范sass和scss,需要分别设置,下面就贴一点vue-cli的代码,不过多的介绍了。
sass

打包运行一下

打包之前可以改改npm scripts,这样就可以看到打包进度,和隐藏不必要的信息

 "build": "webpack --progress --hide-modules"

运行打包

npm run build

前端的环境

  • 开发环境

  • 生产环境

  • 测试环境

  • 预发布环境

  • 上线环境

      - 开发环境  和 生产环境 都是有前端静态服务器来提供
      - 测试环境   本地客户端服务器提供
      - 预发布和上线环境是  nginx  
    
区分开发与生产环境

很多插件功能是在开发环境(development)用到的但是在s生产环境(production)用不到的,反之亦然。比如

-development用到的

  • 热插拔调试
  • 生成html模板

-production

  • 用到的生成html模板
  • css样式提取
  • 公共模块提取
  • JavaScript压缩

第二种方法涉及到二次封装,就像官方vue-cli构建的项目一样,分成了三个配置文件,对目前的我们来说比较复杂,我们使用第一种方法,设置环境变量来区分部署环境。参考vue-cli生成的简单版工程(webpack-simple),我们发现npm script写得有点奇怪

"scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
  }

在运行webpack命令之前运行了 cross-env NODE_ENV=develpoment和production,这就是给环境变量赋值的过程,但是单单这样写是无法执行的,我们需要安装一个插件——cross-env

npm install --save cross-env

这样我们就可以在之后运行在node环境的js 文件中访问到这些环境变量,通过process.env对象还能拿到package.json里面的配置信息,这就涉及到node的知识了,不多说。

const env = process.env.NODE_ENV
//获取工程的版本号const version = process.env.npm_package_version

简单点写,把环境变量的判断直接放到webpack.config.js文件的最下面

const path = require('path')
const webpack = require('webpack')

module.exports = {
    entry:{
        app:'./src/main.js'
    },
    //...
}
/**
 * 生成生产代码的时候才触发
 */if (process.env.NODE_ENV === 'production') {
    // http://vue-loader.vuejs.org/en/workflow/production.html
    module.exports.plugins = (module.exports.plugins || []).concat([
        new webpack.DefinePlugin({
            'process.env': {
            NODE_ENV: '"production"'
            }
        }),
    ])
  }

生成html模板

之前根目录下index.html要我们自己引入js资源地址,有新的资源都要手动引入,很麻烦,这时候就会用到HtmlWebpackPlugin 插件,按照index.html作为模板在dist目录下生成带上所有资源的html 文件。

npm install --save-dev html-webpack-plugin

先通过require引入插件,然后在输出对象里面添加plugins属性,数据值类型是数组,数组成员new 插件添加插件就行。每个插件都有自己的配置项和规范,可以查 npmjs或者 他们的官方文档

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')

module.exports = {
    entry:{
        app:'./src/main.js'
    },
    output:{
        path:path.resolve(__dirname,'./dist'),
        filename:"js/[name].js",
    },
    module:{
        rules:[
        //...
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            filename:'index.html',
            title:'vue demo',
            template:'./index.html',
        })
    ],
    externals:{
        'jquery':'window.jQuery'
    }
}
说明
  • filename 生成的html的文件名,不填就默认是原文件名
  • title title标签的内容
  • template html模板地址,这里我们用我上一期建在跟目录的index.html

index.html的内容要改一改了,因为webpack打包完之后自动添加资源地址到html文件里,所以我们要删掉原本写上去的script标签

<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>vue demo</title></head><body>
    <div id="app">
     
    </div>
    <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.js"></script></body></html>

有人可能会奇怪,这里为什么加了一个cdn的jQuery,因为我要在这里带过一个知识点:有时候我们会有用到cdn加速的库资源,但是不知道怎么在工程中使用。很简单我们在html模板中直接引入,然后在webpack.config.js配置中加一项“外部引入”(externals)

// webpack.config.js
externals:{
    'jquery':'window.jQuery'
}
//app.vue中引入import $ from 'jquery'

热替换

使用热替换之前当然要先有一个web服务器环境啦,安装webpack-dev-server

npm install --save-dev webpack-dev-server

webpack-dev-server其实是一个独立的插件,但是webpack内置了它的配置项,属性devServer对应的就是它的配置项

module.exports = {
    entry:{
        app:'./src/main.js'
    },
    output:{
        path:path.resolve(__dirname,'./dist'),
        filename:"js/[name].js",
    },
    devServer:{
        contentBase:"./dist"
    }
}

端口地址什么的都默认 http://localhost:8080/ ,就设置了跟资源目录地址contentBase。

热替换插件

热替换就是开发的过程中修改文件内容之后不用频繁刷新页面,修改会自动同步到浏览器中,webpack内部已经有这份插件了,不用安装直接都用就可以。在plugins添加一项 new webpack.HotModuleReplacementPlugin()就ok了

plugins:[
        new HtmlWebpackPlugin({
            filename:'index.html',
            title:'vue demo',
            template:'./index.html',
        }),
        new webpack.HotModuleReplacementPlugin()
    ]

改一下npm scripts


"scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
  }

运行 npm run dev,热部署搞定

webpack.config.js配置

单页面
  • 入口文件
    entry: 相对路径
  • 出口文件
  • 配置hash
 output: {
 path: path.resolve(__dirname,'dist'),
 filename: 'js/app_[hash:6].js'
 }
  • 转换器: 将某一类型的文件转成另一个类型文件的一个工具,我们常用loader来表示
  • 举例: css文件
  • 所有的loader用一个module的配置项表示
      module: {
    rules: [
                 {} //每一个对象表示一个类型文件的转换器
               ]
             }
多页面

const path = require('path')
const webpack = require('webpack')
const ExtractTextPlugin = require("extract-text-webpack-plugin")
const ExtractRootCss = new ExtractTextPlugin({filename:'styles/root.css',allChunks:false});
const ExtractVueCss = new ExtractTextPlugin({filename:'styles/[name]/style.css',allChunks:true});

module.exports = {
    //other options...
    module:{
        rules:[
        //...
            {
                test:/\.css$/,
                //这里用的ExtractRootCss
                use:ExtractRootCss.extract({
                    fallback:'style-loader',
                    use:['css-loader']
                })
            },
            {
                test:/\.less$/,
                //这里用的ExtractRootCss
                use:ExtractRootCss.extract({
                    fallback:'style-loader',
                    use:[
                        'css-loader',
                        'less-loader'
                    ]
                })
            },
            {
                test:/\.vue$/,
                loader:'vue-loader',
                options:{
                    loaders:{
                        //这里用的ExtractVueCss
                        'css': ExtractVueCss.extract({
                            use: 'css-loader',
                            fallback: 'vue-style-loader' // <- 这是vue-loader的依赖,所以如果使用npm3,则不需要显式安装
                          }),
                        //这里用的ExtractVueCss
                        'less':
                        ExtractVueCss.extract({
                            use:[
                                'css-loader',
                                'less-loader'
                            ],
                            fallback:'vue-style-loader'
                        })
                    },
                }
            },
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            filename:'index.html',
            title:'vue demo',
            template:'./index.html',
        }),
        ExtractRootCss,//填入插件实例,复用的css
        ExtractVueCss,//记得按顺序填入,vue内的css
        new webpack.HotModuleReplacementPlugin(),
    ]
}

猜你喜欢

转载自blog.csdn.net/xuwei1215225/article/details/89508197