gulp与部分webpack搭建开发环境与项目一些插件的应用和部署nginx

研发环境搭建
yarn add global gulp-cli
yarn add gulp -D
创建gulpfile.js

const {src,series,dest,watch,parallel}=require('gulp')
//series,按顺序依次执行,parallel并行
const sass=require('gulp-sass')//编译scss的插件
const concat=require('gulp-concat')//
const gulpServer=require('gulp-webserver')
const webpackStream=require('webpack-stream')
const proxy=require('http-proxy-middleware')
const path=require('path')


function copyHtml(cb){
    return src('./src/views/**/*.html')//匹配所有得html
    .pipe(dest('./dev/'))//目标地址
    cb();
}
function compileCss(){
    return src('./src/style/**/*.scss')
    .pipe(sass().on('error',sass.logError))
    .pipe(concat('all.css'))
    .pipe(dest('./dev/'))
}
function compileJs(){
    // return src('./src/js/**/*.js')
    // .pipe(dest('./dev/'))
    return src('./src/js/**/*.js')
    .pipe(webpackStream({
        mode:'development',
        entry:{
            main:'./src/js/app.js',
            detail:'./src/js/Detail.js',
        },
        devtool:'#inline-source-map',//网页显示源代码,方便调试
        output:{
            //完整的输出目录
            path:path.resolve(__dirname,'./dev/'),
            filename:'[name].js'
        },
        //转es5
        module:{
            rules:[ //规则
                {
                    test:/\.js$/,//.js的文件进行处理
                    exclude:/node_modules/,//排除选项文件夹
                    use:{
                        loader:'babel-loader',
                        options:{
                            presets: ['@babel/preset-env'],//预设
                            plugins: ['@babel/plugin-transform-runtime']//插件程序
                        }
                    }
                },{
                    test:/\.html$/,
                    loader:'string-loader'
                }
            ]
        }
    }))
    .pipe(dest('./dev/'))
}
function startServer(){
    return src('./dev').pipe(gulpServer({
        port:8008,
        host:'127.0.0.1',
        //是否支持热更新
        livereload: true,
        directoryListing: false,
        open: true,
        middleware:[
            proxy('/api',{
                target:'http://localhost:3003/polistionlist',//代理的目标地址
                changeOrigin:true,//是否支持跨越
                /* pathRewrite:{
                    '^/api':''
                } */
            })
        ]
    }))
}
function copyLibs(){
    return src('./src/libs/**/*.*')
    .pipe(dest('./dev/libs/'))
}
function copyImg(cb){
    return src('./src/image/**/*.*')//匹配所有得html
    .pipe(dest('./dev/image/'))//目标地址
    cb();
}
function watchFile(){
    watch('./src/style/**/*.scss',(cb)=>{
        compileCss()
        cb()
    })
    watch('./src/js/**/*.js',(cb)=>{
        compileJs()
        cb()
    })
    watch('./src/views/**/*.html', (cb) => {
        copyHtml();
        compileJs();
        cb();
      })
}
exports.default=series(parallel(copyHtml,copyLibs,copyImg),compileCss,compileJs,
    startServer,watchFile)

执行gulp 就可以

安装yarn add gulp-webserver -D//搭建研发的server

yarn add node-sass gulp-sass -D//编译scss

yarn add webpack-stream -D//编译js文件
yarn add babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime @babel/runtime //一些es678的转化为es5

yarn add string-loader -D
在这里插入图片描述

移动端一像素适配
//sass混合器;
如果你的整个网站中有几处小小的样式类似(例如一致的颜色和字体),那么使用变量来统一处理这种情况是非常不错的选择。但是当你的样式变得越来越复杂,你需要大段大段的重用样式的代码,独立的变量就没办法应付这种情况了。你可以通过sass的混合器实现大段样式的重用。

混合器使用@mixin标识符定义。看上去很像其他的CSS @标识符,比如说@media或者@font-face。这个标识符给一大段样式赋予一个名字,这样你就可以轻易地通过引用这个名字重用这段样式。下边的这段sass代码,定义了一个非常简单的混合器,目的是添加跨浏览器的圆角边框。

@mixin border_1px($color) {
    position: relative;
    //可否区分屏幕
    @media(-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5) {
        &::before{
            content: '';
            position: absolute;
            left: 0px;
            top: 0px;
            background-color: $color;
            transform: scaleY(0.75);//缩放一半
            height: 1px;
            width: 100%;
        }
    }
    @media(-webkit-min-device-pixel-ratio:3),(min-device-pixel-ratio:3) {
        &::before{
            content: '';
            position: absolute;
            left: 0px;
            top: 0px;
            background-color: $color;
            transform: scaleY(0.33);//缩放一半
            height: 1px;
            width: 100%;
        }
    }
    @media(-webkit-min-device-pixel-ratio:2),(min-device-pixel-ratio:2) {
        &::before{
            content: '';
            position: absolute;
            left: 0px;
            top: 0px;
            background-color: $color;
            transform: scaleY(0.5);//缩放一半
            height: 1px;
            width: 100%;
        }
    }
}
移动端特有的touch事件

touch事件与click事件同时触发
touchstart=>touchend=>click(200-300ms延迟)
可以通过event.preventDefault()

touchstart事件是移动端特有事件
touchmove手指移出target元素,则touchmove会被一直触发,需要考虑事件节流,(移动端计算资源非常宝贵)
touchend和touchmove打印的e.target的内容是一样
touchcancel模态对话框,(电话)就会调用这个事件

触摸事件的对象

TouchEvent:

<script>
        window.onload=function(){
            var box=document.querySelector('div')
            box.addEventListener('touchstart',function(e){
                console.dir(e)
            })
        }
    </script>

TouchList

window.onload=function(){
            var box=document.querySelector('div')
            var p=document.querySelector('p')
            box.addEventListener('touchend',function(e){
                //返回touch对象的个数,移动端就可以获取几根手指触摸的事件
                p.innerHTML=e.changedTouches.length
                for (let i = 0; i < e.changedTouches.length; i++) {
                    console.log(e.changedTouches.item(i))
                    
                }
            })
        }

Touch
clientX: 234.40000915527344//触摸点相对于浏览器(视图窗口)左边的坐标
clientY: 24.199996948242188
force: 0//按压力度
identifier: 0//每一个touch对象唯一的id,通过它追踪每一个touch对象
pageX: 234.40000915527344//触摸点相对于document左边的坐标(会包含滚动条的距离)
pageY: 24.199996948242188
radiusX: 11.5
radiusY: 11.5
rotationAngle: 0
screenX: 717.6000366210938//触摸点相对于屏幕左边的坐标
screenY: 236

合作模式,模拟数据

yarn aglobal add json-server
启动json-server服务:json-server ./mock/data.json
//也可以单独配置
json-server ./mock/data.json -p 3333(端口) -w(观测变化) i(指定数据) id -s(静态资源目录)

可以直接在package.json里面配置,执行npm run mock就可以
在这里插入图片描述

如果有其他路径,可以配置
routes.json文件
在这里插入图片描述

入口页面
在这里插入图片描述

最后在package.json里面配置data
在这里插入图片描述
当数据模拟成功,使用模板引擎
npm install art-template --save或者下载文件
在这里插入图片描述
传输数据:
在这里插入图片描述
以$value来接受
在这里插入图片描述

//https://better-scroll.github.io/docs/zh-CN/guide/how-to-install.html#npm
移动端下拉刷新,安装插件better-scroll
yarn add @better-scroll/core@next
//下拉刷新
yarn add @better-scroll/pull-down@next
//上拉加载更多
yarn add @better-scroll/pull-up@next
在这里插入图片描述
要求:唯一的子节点,子节点必须超出包裹的高度,html内容必须已经渲染完

//配置下拉刷新,需要下拉的外容器
        this.scroll=new BScroll('#position-wrapper',{
            scrollY:true,
            pullDownRefresh:{
                threshold:40,//下拉40触发事件
                stop:0//当下来恢复原位需要手动设置0,默认40的高度
            }
        })
        //下拉刷新
        this.scroll.on('pullingDown',async()=>{
            await this.getlist()//获取数据
            // 每次触发下拉事件后,在回调函数的最后,都应该调用 finishPullDown() 
            this.scroll.finishPullDown();
        })
        //检测实时滚动
        this.scroll.on('scroll',function(){
            if(this.y>20){
                $(".refersh").show()
            }else{
                $(".refersh").hide()
            }
        })

//分页条件
http://localhost:3003/polistionlist?_page=0&_limit=3

refresh()
参数:无
返回值:无
作用:重新计算 BetterScroll,当 DOM 结构发生变化的时候务必要调用确保滚动的效果正常。

//路由切换,地址栏的前进和后退

//三个页面的点击,添加属性data-url
<ul id="nav">
      <li class="active" data-url="position">
       <i class="iconfont">&#xeb9d;
       </i>职位</li>
       <li data-url="search">
        <i class="iconfont">&#xeb8f;
        </i>搜索</li>
      <li data-url="main">
        <i class="iconfont">&#xeb9e;
        </i>我的</li>
 </ul>
//----------------------
 //入口文件app.js
import Router from '../js/router/router'//路由的文件
const MODE='hash';
// const MODE='history';
class App{
    constructor(){
        this.router=new Router({
            mode:MODE//哈希或者hisory的方式传过去
        })
        this.initEvent()
    }     
 initEvent(){
    var self=this
    $("#nav li").on('click',function(){
            $(this).addClass('active').siblings().removeClass('active')//样式切换
            let url=$(this).attr('data-url')//取到url
            self.router.go(url)//点击后执行router下面的go方法,将url传过去
     })
     //----------------------
      // -----页面强制刷新,不会跳转
        addEventListener('load',()=>{
            let url=location.hash.replace('#','')||'position';
            if(MODE==='history'){
                url=history.state?history.state.path:'position';
            }
            this.router.go(url)
            this.setActive(url)
        })
        // -----
        //前进和后退
        if(MODE==='hash'){
            addEventListener('hashchange',()=>{
                let hash=location.hash.replace('#','');
                self.router.go(hash)
                this.setActive(hash)
            })
        }else{
            $(window).on('popstate',()=>{
                console.log(history.state)
                let url=history.state.path;
                self.router.go(url)
                this.setActive(url)
            })
        }
        //激活哪个active
       setActive(url){
        $('#nav').find('li[data- url="'+url+'"]').addClass('active').siblings().removeClass('active')
    }
 }      

router.js文件

import position from '../controller/positionController'
import search from '../controller/searchController'
import main from '../controller/profileController'
//-------以上是三个页面
class Router{
   constructor(options){
        this.mode=options.mode;
        console.log(options)//hash或者history
        this.routes={
            //三个路由
            'position':position,
            'search':search,
            'main':main//前面的key必须和data-url设置的一样
        }
    }
    go(path){
        if(this.mode==="hash"{
           location.hash=path;//地址栏加入path
        }else{
            history.pushState({path},'',"?"+path)
        }
        this.loadview(path)//然后执行去向点击的页面
    }
    loadview(path){
        if(this.routes[path]){
            this.routes[path].render()//然后执行去向点击的页面
        }else{
            //404 找不到
        }
    }
}

swiper左右滑动
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    //引入的css
    <link rel="stylesheet" href="https://unpkg.com/swiper/css/swiper.min.css"> 
    <style>
        .swiper-container {
            width: 600px;
            height: 300px;
        }
    </style>
</head>

<body>
    <div class="swiper-container">
        <div class="swiper-wrapper">
            <div class="swiper-slide">Slide 1</div>
            <div class="swiper-slide">Slide 2</div>
            <div class="swiper-slide">Slide 3</div>
        </div>
        <!-- 如果需要分页器 -->
        <!-- <div class="swiper-pagination"></div> -->
        <!-- 如果需要导航按钮 -->
        <!-- <div class="swiper-button-prev"></div> -->
        <!-- <div class="swiper-button-next"></div> -->
        <!-- 如果需要滚动条 -->
        <!-- <div class="swiper-scrollbar"></div> -->
    </div>
    <!-- 导航等组件可以放在container之外 -->
    //引用的js
    <script src="https://unpkg.com/swiper/js/swiper.min.js"> </script>
    <script>        
        var mySwiper = new Swiper ('.swiper-container', {
        //   direction: 'vertical', // 垂直切换选项
          loop: true, // 循环模式选项
          
          // 如果需要分页器
        //   pagination: {
        //     el: '.swiper-pagination',
        //   },
          
          // 如果需要前进后退按钮
        //   navigation: {
        //     nextEl: '.swiper-button-next',
        //     prevEl: '.swiper-button-prev',
        //   },
          
          // 如果需要滚动条
        //   scrollbar: {
        //     el: '.swiper-scrollbar',
        //   },
        })        
        </script>
</body>
</html>

//配置多页面

entry:{
            main:'./src/js/app.js',
            detail:'./src/js/detail.js',//详情页面
        },
        devtool:'#inline-source-map',//网页显示源代码,方便调试
        output:{
            //完整的输出目录
            path:path.resolve(__dirname,'./dev/'),
            filename:'[name].js'
        },

在这里插入图片描述
当使用better-scroll时候会阻止原生js的一些事件所以配置时候需要将click设置为true

//项目打包
//生产环境的配置

const {src,series,dest,watch,parallel}=require('gulp')
//series,按顺序依次执行,parallel并行
const sass=require('gulp-sass')//编译scss的插件
const concat=require('gulp-concat')//
const webpackStream=require('webpack-stream')
const del=require('del')
const path=require('path')
const rev=require('gulp-rev')
const revCol=require('gulp-rev-collector')

function copyHtml(cb){
    return src('./src/views/**/*.html')//匹配所有得html
    .pipe(dest('./dist/'))//目标地址
    cb();
}
function compileCss(){
    return src('./src/style/**/*.scss')
    .pipe(sass().on('error',sass.logError))
    .pipe(concat('all.css'))
    .pipe(rev())
    .pipe(dest('./dist/'))
    .pipe(rev.manifest())
    .pipe(dest('./rev/'))//生成一个json文件,原来的css和现在的css
}
function compileJs(){
    // return src('./src/js/**/*.js')
    // .pipe(dest('./dev/'))
    return src('./src/js/**/*.js')
    .pipe(webpackStream({
        mode:'production',
        entry:{
            main:'./src/js/app.js',
            detail:'./src/js/Detail.js',
        },
        output:{
            //完整的输出目录
            path:path.resolve(__dirname,'./dist/'),
            filename:'[name].js'
        },
        //转es5
        module:{
            rules:[ //规则
                {
                    test:/\.js$/,//.js的文件进行处理
                    exclude:/node_modules/,//排除选项文件夹
                    use:{
                        loader:'babel-loader',
                        options:{
                            presets: ['@babel/preset-env'],//预设
                            plugins: ['@babel/plugin-transform-runtime']//插件程序
                        }
                    }
                },{
                    test:/\.html$/,
                    loader:'string-loader'
                }
            ]
        }
    }))
    .pipe(rev())
    .pipe(dest('./dist/'))
    .pipe(rev.manifest())
    .pipe(dest('./rev/'))
}

function copyLibs(){
    return src('./src/libs/**/*.*')
    .pipe(dest('./dist/libs/'))
}
function copyImg(cb){
    return src('./src/image/**/*.*')//匹配所有得html
    .pipe(dest('./dist/image/'))//目标地址
    cb();
}
function remove(){
    return del('./dist/')
}
function revColl(){
    //替换文件,将打包里面的dist的html,替换生成的哈希文件
    return src(['./rev/*.json','./dist/*.html'])
    .pipe(revCol())
    .pipe(dest('./dist/'))
}


exports.default=series(remove,parallel(copyHtml,copyLibs,copyImg),compileCss,compileJs,revColl)

配置package.json

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "mock": "json-server ./mock/positionlist.json -w -p 3003",
    "data": "json-server ./mock/mock.js -r ./mock/routes.json -p 8088",
    "dev":"gulp -f ./gulpfile.dev.js",
    "build":"gulp -f ./gulpfile.pro.js"
  },

执行yarn build

如果文件太大,需要调小
比方第三方插件的引用可以换一种方式导入

// import BScroll from '@better-scroll/core'
// import PullDown from '@better-scroll/pull-down'
// import Pullup from '@better-scroll/pull-up'
//不使用import导入
//去下载原来的batter-scroll.js文件,在入口页面导入

在这里插入图片描述

部署之前删除目录下的文件
yarn add del -D
function remove(){
return del(’./dist/’)
}
文件名后面加随机hash值,防止浏览器缓存问题,当文件有改动,用户访问时候新的路径便不会缓存
插件gulp-rev
yarn add gulp-rev -D
yarn add gulp-rev-collector -D

//列如css文件
function compileCss(){
    return src('./src/style/**/*.scss')
    .pipe(sass().on('error',sass.logError))
    .pipe(concat('all.css'))
    .pipe(rev())
    .pipe(dest('./dist/'))
    .pipe(rev.manifest())
    .pipe(dest('./rev/'))//生成一个json文件,原来的css和现在的css
}
function revColl(){
    //替换文件,将打包里面的dist的html,替换生成的哈希文件
    return src(['./rev/*.json','./dist/*.html'])
    .pipe(revCol())
    .pipe(dest('./dist/'))
}

生成的json文件
在这里插入图片描述

部署到nginx

nginx是反向代理服务器,跨平台,配置简单,内存消耗小。官方支持五万并发,支持GZP压缩,通信机制采用epoll模型
动态资源,静态资源分离
易于性能优化。

安装nginx
在mac上:brew install nginx
默认安装目录:/usr/local/etc/nginx/
nginx //启动服务
nginx -s stop//停止服务
nginx -s reload//重启服务
在windows:
官网下载安装包,解压之后
在这里插入图片描述
然后双击打开nginx.exe当在地址栏输入localhost显示下图就成功打开
在这里插入图片描述
打开conf文件夹.配置
在这里插入图片描述
然后再指定目录下建一个conf.d文件夹,里面再建一个**.conf文件,配置
server{
listen 9999;
#用来IP地址或者域名,多个域名用空格隔开
server_name localhost;
#文件路径
root D:\1000phone\third-one\dist;
#默认访问页面
index index.html;
location /api{
#路径重写
rewrite /api/(.*) /$1 break;
#代理的目标地址
proxy_pass http://127.0.0.1:3003/;
}
}

项目最后效果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值