• 使用webpack打包ThinkPHP的资源文件


    使用webpack打包ThinkPHP的资源文件

    利用自己的空余时间一直在维护http://www.wx2share.com这个小网站,全是一个人在弄,由于只租得起虚拟空间,所以后台采用了简单方便的ThinkPHP反正主要也是做一些CURD操作ThinkPHP还是挺好用的,帮我提前做好了好多功能。
    本人并不擅长前端,但是开始开发这个小网站发现,基本的功能全部要通过前端javascript来实现。一开始的时候所有的javascript代码全部写在html页面里。也没有太大问题,后来为了页面性能要求把所有javascript和css全部minify一下。我采用的办法把js和css通过资源文件引入。然后用在线的minify工具复制过去minify以后,复制回来保存为xxx.min.js。方法是笨一点,但是一来页面不多,到也没有多麻烦。但是渐渐的页面开始多了以后,就越来越不方便了。

    原来方法中的痛点

    • 每次minify都要复制来复制去,文件多了麻烦
    • 代码重复利用率不高。
    • 办法1:重复代码全部复制到新文件(傻)
    • 办法2:公用代码保存为单独文件分别引入,不利入页面性能

    这时候让我不得不考虑使用前端自动化构键工具

    构键工具的选择

    我对工具的要求不高,一开始纯粹主是我了minify js和css所以一开始我选用了gulp,因为用过所以直接就用了

    gulp的方案

    打包第三方的javascript类库

    gulp.task('vendor',()=>
    	gulp.src([
    		'bower_components/jquery/dist/jquery.js',
    		'bower_components/bootstrap/dist/js/bootstrap.js',
    		'src/lib/bootstrap-modal.js',
    		'src/lib/bootstrap-modalmanager.js',
        	'bower_components/jquery.cycle2/index.js'
    		]).pipe(concat('vendor.js'))
    		  .pipe(gulpif(production,uglify({ mangle:true })))
    		  .pipe(gulp.dest('Public/Home/js'))
    	);
    

    不错,完美。只要 NODE_ENV=production 时还能自动压缩和混淆js

    minify css并拷贝图片Public对应目录。

    gulp.task('styles',()=>
    	gulp.src('src/css/show.css')
    		.pipe(plumber())
    		.pipe(autoprefixer())
    		.pipe(gulpif(production,cssmin()))
    		.pipe(gulp.dest('Public/Home/css'))
    );
    
    gulp.task('img',()=>
    	gulp.src('src/img/*')
    	.pipe(gulp.dest('Public/Home/img'))
    );
    
    gulp.task('watchcss',()=>
    	gulp.watch('src/css/**/*.css',['styles'])
    );
    

    也很不错,通过gulp.watch还实现CSS实时更新。

    打包自己的js文件

    gulp.task('browserify', () =>{
      var bundler = browserify({
      	//entries:['src/js/pcshowpage.js'],
      	entries:['src/js/pcshowpage/index.js'],
      	standalone:'pcshowpage',
      	cache:{},
      	packageCache:{},
      	plugin:[]
      })
      bundler.transform(babelify,{ presets: ["es2015"]});
    
        bundler.bundle()
        .pipe(source('pcshowpage.js'))
        .pipe(buffer())
        .pipe(sourcemaps.init({loadMaps: true}))
        .pipe(gulpif(production, streamify(uglify({ mangle: true }))))
        .pipe(sourcemaps.write('./'))
        .pipe(gulp.dest('Public/Home/js'))}
    );
    

    相当以及完全的完美,通过babel的转译还能愉快的用ES6来写代码了,什么新特性都能用来了。代码也能模块化了。不同的功能写成不同的模块,只要import 一下就可以用了。gulp通过browserify帮你转译成浏览器能识别的ES5写起代码来非常愉快。
    通过watchify也能实现代码的实时更新

    gulp.task('browserify-watch', () =>{
      //var bundler = watchify(browserify('src/js/pcshowpage.js', watchify.args));
      var bundler = browserify({
      	//entries:['src/js/pcshowpage.js'],
      	entries:['src/js/pcshowpage/index.js'],
      	standalone:'pcshowpage',
      	cache:{},
      	packageCache:{},
      	plugin:[watchify]
      })
      bundler.transform(babelify,{ presets: ["es2015"]});
      bundler.on('update', rebundle);
      return rebundle();
    
      function rebundle() {
        var start = Date.now();
        bundler.bundle()
          .on('error', function(err) {
            gutil.log(gutil.colors.red(err.toString()));
          })
          .on('end', function() {
            gutil.log(gutil.colors.green('Finished rebundling in', (Date.now() - start) + 'ms.'));
          })
          .pipe(source('pcshowpage.js'))
          .pipe(buffer())
          .pipe(sourcemaps.init({loadMaps: true}))
          .pipe(sourcemaps.write('./'))
          .pipe(gulp.dest('Public/Home/js'));
      }
    });
    

    看起来非常的美好了,愉快的写完了这个页面开始重构别一个页面的时候,问题来了,我不会用gulp定义多个出口文件,(就是我不会,没用过而已,gulp肯定能做到的)我也知道用代码来定义多个bundler肯定是做到,但是我满脑子就想到了webpack定义多个出口文件是多么方便。所以我就对gulp始乱终弃了。

    webpack的方案

    	entry: {
    	    css:"./src/css/index.js",
    	    mainpage:"./src/js/mainpage/index.js",
    	    pcshowpage: "./src/js/pcshowpage/index.js",
    	    combpage:"./src/js/combpage/index.js",
    	    tbkpage:"./src/js/tbkpage/index.js",
    	  },
    	  output: {
    	    library: '[name]',
    	    libraryTarget: "umd",
    	    path: path.resolve(__dirname, PublicPath),
    	    filename: 'js/[name].js'
    	  }
    

    就这么简单明了,每个js文件生成了单独的输出文件。不同的页面引入不同的js就好了。接下来通过CommonsChunkPlugin抽取公用的模块到common.js,

    	new webpack.optimize.CommonsChunkPlugin({
          name: "common",
          minChunks : 2,
          chunks:["mainpage","pcshowpage","combpage","tbkpage"]
        }),
    

    这样一些几个页面通用的代码都被抽到common.js中了。其它图片,CSS, Font等内容全部由不同的loader来处理,看起来比gulp明了多了。

    开发与产生环境不同生成的配置。

    开发环境

    在目录下,新建一个dev.js

    require('shelljs/global')
    
    var merge   = require('webpack-merge')
    
    var path = require('path')
    
    var webpack = require('webpack')
    
    var webpackConfig = require('./webpack.config')
    
    var devcoifng=merge(webpackConfig, {
      devtool: '#eval-source-map', //可以理解为继承通用配置,在dev模式下生成source map 方便调试。
    })
    
    var c=webpack(devcoifng);
    
    c.watch({ // watch options:
        aggregateTimeout: 300, // wait so long for more changes
        poll: true // use polling instead of native watchers
        // pass a number to set the polling interval
    }, function(err, stats) {
       if (err) throw err
      	process.stdout.write(stats.toString({
        colors: true,
        modules: false,
        children: false,
        chunks: false,
        chunkModules: false
      }) + '
    ')
    });
    

    运行 node dev.js

    通过wath()实现了,代码的实时更新。修改完js代码一保存,资源目录下的文件就可以更新,刷新一下页面就可以载入最新的代码了。debug的时候由于有source map 就可以看清到底是哪里的代码有问题,还支持单步调试。

    生成环境

    由于生成环境还需要配置的东西更多,所以我新建了一个prod.conf.js

    var webpack = require('webpack')
    var merge   = require('webpack-merge')
    var baseWebpackConfig = require('./webpack.config')
    
    module.exports = merge(baseWebpackConfig, {
    	plugins: [
        new webpack.DefinePlugin({
          'process.env': {
            NODE_ENV: 'production'
          }
        }),
        new webpack.optimize.UglifyJsPlugin({ //压缩混淆代码
          compress: {
            warnings: false
          }
        }),
        new webpack.optimize.OccurenceOrderPlugin(),
        // extract css into its own file
       
      ]
    })
    

    再建一个build.js

    require('shelljs/global')
    env.NODE_ENV = 'production'
    
    var path = require('path')
    
    var webpack = require('webpack')
    
    var webpackConfig = require('./webpack.prod.conf')
    
    webpack(webpackConfig, function (err, stats) {
      if (err) throw err
      process.stdout.write(stats.toString({
        colors: true,
        modules: false,
        children: false,
        chunks: false,
        chunkModules: false
      }) + '
    ')
    })
    

    只要运行 node build.js

    就可以生成已经压缩混淆好的js和css了,可以说相当的方便了

    还没有解决的问题

    • 竟然没有办法仅仅把代码contact在一起的办法,我的vendor文件还是用gulp生成的,还好这个文件基本上不怎么修改。我过通过定义
    var dependencies = [
        './bower_components/jquery/dist/jquery.js',
        './bower_components/bootstrap/dist/js/bootstrap.js',
        './src/lib/bootstrap-modal.js',
        './src/lib/bootstrap-modalmanager.js',
        './bower_components/jquery.cycle2/index.js'
      ]
    
      ........
    
    //然后在 entry 加入 
    
    entry:{
    	vendor:dependencies
    	........
    	.......
    }
    
    //再配置一个
    new webpack.optimize.CommonsChunkPlugin({
          name: "vendor",
          minChunks : Infinity,
        }),
        .....
    
    

    这样生成的vendor文件里面所有的类库全变成AMD JS 规范了再页面中引入没有办法正常使用jquery等类库,gulp contact的做法就是简单把几个文件合并在一起而已,在页面中引入不影响使用,

    • 还有一个问题是CDN引起的问题。

    由于我的html模版页面还是自己写的,而且没有用webpack处理,因为我用了thinkphp的模版功能,页面的header footer 我定义在base.html中,其它页面继承一下,这样,好多重复代码就不用写了。但是也没有办法用html-webpack-plugin来处理了,为了解决CDN缓存问题,我给每个资源文件加了一个时间戳,每次都要手动去改一下好麻烦
    希望大家能提供好的方法来帮我解决这两个问题。

  • 相关阅读:
    深入PHP内核之全局变量
    关于PHP中的opcode
    深入PHP内核之opcode handler
    virtual memory exhausted: Cannot allocate memory
    Nginx配置error_page 404错误页面
    PHP 与 UTF-8
    define() vs const 该如何选择?
    CentOS安装配置Samba
    当···时发生了什么?
    PHP中curl的使用
  • 原文地址:https://www.cnblogs.com/9527/p/6220647.html
Copyright © 2020-2023  润新知