使用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
}) + '\n')
});
运行 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
}) + '\n')
})
只要运行 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缓存问题,我给每个资源文件加了一个时间戳,每次都要手动去改一下好麻烦
希望大家能提供好的方法来帮我解决这两个问题。
使用webpack打包ThinkPHP的资源文件的更多相关文章
- Pyinstaller打包: 将资源文件或文件夹打包到最后生成的exe中
前提:用pyinstaller打包时部分资源文件可以利用qrc转成py文件来读取,但是有部分文件类型不适用. 原理:Pyinstaller 将资源文件一起打包到exe中.当exe运行时,会生成一个临时 ...
- vue2.0 配置build项目打包目录、资源文件(assets\static)打包目录
vue项目默认的打包路径:根目录下的dist文件夹下: 但是在项目开发中,我们肯定希望项目提交到svn目录或者git目录下,否则每次复制过去,太麻烦了: 那怎么配置打包路径呢?下面来看看: 我们找到打 ...
- angular4.0 配置打包路径以及资源文件404问题
一.配置打包路径 配置打包路径,便于提交到SVN,不用每次都复制粘贴 在.angular-cli.json文件中修改"outDir"的路径,打包后的项目将发布到路径下 二.解决打包 ...
- maven打包额外的资源文件
在用Maven打包的时候发现,有一些资源文件打包不到jar包中,于是了解了一下Maven的打包配置,最后得到了解决问题的办法. Maven资源文件的默认约定 构建Maven项目的时候,如果没有进行特殊 ...
- 关于使用maven打包如何聚合资源文件
多数情况下,我们使用maven管理多个子工程,在最后maven打包阶段将多个子工程聚合到一个jar或war包.单个子工程会有自己独立的资源配置文件,在打包的时候我们需要将其聚合在一起(各子工程中的配置 ...
- webpack打包多个入口文件
打包后的目录结构: webpack.config.js // path 模块提供了一些用于处理文件路径 const path = require('path'); // fs模块用于对系统文件及目录进 ...
- vue项目通过webpack打包生成的dist文件放到express环境里运行(vue+webpack+express)
1.首先需要的原料肯定是vue打包生成的dist文件 在vue项目目录下运行:npm run build,等待运行结束,会在项目目录下生成一个dist文件夹,里面会生成一些文件(如下图示) 小的项目文 ...
- webpack打包指定HTML的文件并引入指定的chunks
1. 安装 html-webpack-plugin npm install html-webpack-plugin --save-dev 2. 在webpack.config.js中配置 const ...
- webpack打包优化并开启gzip
应用场景:项目使用webpack2.x进行打包,打包后静态资源通过nginx转发配置: 问题:webpack打包后的资源文件特别,特别大,没打包之前页面一个页面js有2M左右(其中已经抽离了css)? ...
随机推荐
- *关于httl开源Java模板的使用心得
1.简介 HTTL (Hyper-Text Template Language) 是一个高性能的开源JAVA模板引擎, 适用于动态HTML页面输出, 可替代JSP页面, 指令和Velocity相似. ...
- bzoj 3714
题意:n<=2000的盒子,有一些里面有球,再给你所有c[i][j](1<=i<=j<=n),即告诉你[i,j]里面球的总数的奇偶性需要花费c[i][j],现在求知道所有的盒子 ...
- 【转】C#Winform程序如何发布并自动升级(图解)
有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布关于打包的大家可以看我的文章C# winform程序怎么打包成安装项目(图解)其实打包是打包,发 ...
- 配置tomcat编码格式
tomcat默认编码格式为“ISO-8859-1”,打开tomcat的“server.xml”文件,找到下面行并修改 <Connector connectionTimeout="200 ...
- [.NET领域驱动设计实战系列]专题八:DDD案例:网上书店分布式消息队列和分布式缓存的实现
一.引言 在上一专题中,商家发货和用户确认收货功能引入了消息队列来实现的,引入消息队列的好处可以保证消息的顺序处理,并且具有良好的可扩展性.但是上一专题消息队列是基于内存中队列对象来实现,这样实现有一 ...
- AMD加载器实现笔记(二)
AMD加载器实现笔记(一)中,我们实现了一个简易的模块加载器.但到目前为止这个加载器还并不能称为AMD加载器,原因很简单,我们还不支持AMD规范中的config配置.这篇文章中我们来添加对config ...
- 【原创】GC/垃圾回收简介
GC简介 1 GC机制 1.1 对象 从计算机的角度,装有数据的内存空间 1.2 作用 将内存垃圾的释放自动化 1.3 本质 将已经引用不到的对象视为死亡,将死亡的对象找出来并且作为垃圾进行回收 2 ...
- JavaScript函数柯里化
函数式 JavaScript是以函数为一等公民的函数式语言.函数在JavaScript中也是一个对象(继承制Function),函数也可以作为参数传递成函数变量.最近几年函数式也因为其无副作用的特性. ...
- 把 Notepad++ 打造成一款易用的C#脚本编辑器
以前一直用Linqpad在写小程序脚本,但是Linqpad自动完成功能要收费,且不开源,这样的话就不方便扩展了.今天在 http://csscriptnpp.codeplex.com/ 发现了一款C# ...
- 如何将GridViewEX升级到UWP(Universal Windows Platform)平台
引言 上一篇文章中,我们主要讲解了如何在保证GridView控件的用户体验基础上,扩展GridView生成GridViewEx控件,增加动态添加新分组功能等,本文在上文的基础上,介绍如何在Window ...