Table of Contents
这几天写了一个诗词网站的一个 demo。目的是练习 vue 以及 webpack。之所以选择诗词网站,一是手上有诗词的数据库(从一个诗词软件里拷贝过来的)。二是不算复杂,适合练手。下面回忆一下练习中碰到的问题。
文章最初分布在简书,时间为 2018.06.17 20:41 。
链接:https://www.jianshu.com/p/969f9529aa01
首先,是整体规划的问题
虽然是个小 demo,也许正因为是个小 demo ,所以没有详细规划,想到一个功能写一个功能,想到一个页面写一个页面。结果就是组件改了又改,束手束脚,后台 php 也是不停的更改。不过好歹是写出来了。差点忘了,先放一下目录结构。
./src/
|-- assets
| |-- font
| | |-- iconfont.eot
| | |-- iconfont.svg
| | |-- iconfont.ttf
| | `-- iconfont.woff
| |-- js
| | |-- base.js
| | `-- iconfont.js
| `-- styles
| |-- iconfont.css
| `-- main.less
|-- home.html
|-- index.js
|-- index.php
`-- poem
|-- article
| |-- article.html
| |-- article.js
| `-- articlebody.vue
|-- author.vue
|-- authors
| |-- authors.js
| `-- styles
| `-- authors.less
|-- body.vue
|-- footer.vue
|-- header.vue
|-- poem.vue
|-- poems
| |-- pages.vue
| |-- poems.js
| `-- poemsbody.vue
`-- search
|-- search.js
`-- searchbody.vue
目录比较乱。assets 目录下包含 font、js、styles。其中 base.js 并未用到。首页的文件直接在 src 文件夹下,需要的组件在 poem 文件下。其余的页面也在 poem 文件夹下。除了首页,其他页面共用 article.html 模板。实际上可以都用首页的,因为结构是一样的。
组件调用有点混乱,主要是没有统一放到一个文件夹里,而是散落在各个页面文件夹里。以后的项目还是注意点好。
二、 vue 引入的问题。
一开始写的是:
import Vue from "vue"
结果报错了,因为这句话导入的并不是 vue.js,而是vue.common.js。将其改成下面的就好了。
import Vue from "vue/dist/vue.js"
于是问题又来了,之前的练习 TodoApp 里使用的就是第一句,为什么那里没有问题呢?查看了一下代码,原来 TodoApp 里入口文件使用的是 render,而不是 components 属性。至于 vue.js 和 vue.common.js 的不同可以查考下面的文章:
Vue 2.0 升(cai)级(keng)之旅
webpack+vue的匹配报错
三、 webpack 多页面问题
关于 webpack 多页面的问题,在写这个 demo 之前就已经百度了很多,但都没弄懂。所以,一开始写这个 demo 的时候就用了一个页面一个配置文件的方法,等到写完在慢慢折腾 webpack。下面就是折腾的结果:
const config = {
……
entry: {
index: './src/index.js',
authors: './src/poem/authors/authors.js',
poems: './src/poem/poems/poems.js',
search: './src/poem/search/search.js',
article: './src/poem/article/article.js'
},
output: {
filename: "js/[name].[chunkhash:8].js",
path: path.resolve(__dirname,'dist')
},
……
plugins: [
……
new HTMLPlugin({
template: './src/home.html',
filename: './home.html',
chunks: ['lib','index']
}),
new HTMLPlugin({
template: './src/poem/article/article.html',
filename: 'poems.html',
chunks: ['lib','poems']
}),
new HTMLPlugin({
template: './src/poem/article/article.html',
filename: 'authors.html',
chunks: ['lib','authors']
}),
new HTMLPlugin({
template: './src/poem/article/article.html',
filename: 'article.html',
chunks: ['lib','article']
}),
new HTMLPlugin({
template: './src/poem/article/article.html',
filename: 'search.html',
chunks: ['lib','search']
})
],
……
}
其中 lib 是拆包出来的公共库。我这里没有碰到 js 加载顺序的问题,如果有顺序问题,可以配置 html-webpack-plugin 插件的 chunksSortMode: 'manual' 解决问题。
四、 公共库打包问题
关于公共库打包折腾了很久。总体来说是配置不了解的问题。一开始配置大致如下:
new webpack.optimize.SplitChunksPlugin({
name:'vendor'
}),
打包后发现,lib.js 文件确实存在了,文件也引入了,但是,其他的 js 文件体积并没有减小。(这里存在这个文件是因为有 lib 入口,而不是真的剥离公共库。)为什么?然后又是一通百度,总算找到了解决方法。SplitChunksPlugin 的配置应该这么写:
optimization: {
splitChunks: {
cacheGroups: {
lib: {
name: 'lib',
filename: 'js/[name].[chunkhash:8].js',
minChunks: 2,
chunks: 'initial'
}
}
}
}
这个 optimization 应该在 config 下面,和 entry 平级。
好了,总算解决了。
五、css 拆分的问题
嗯,实际上,这个问题还没有解决。通过 mini-css-extract-plugin 确实可以将 css 剥离出来,但是,页面没有内容,控制台也没有报错。😭
所以,css 剥离只能暂时放弃了。
六、 环境配置问题
平时为了开发方便,引入的库都是未压缩的。环境设置为 development ,但上线时需要改为 production 。为了切换方便,以及解决跨平台问题。需要使用 cross-env 插件。package.json 脚本如下:
"build": "cross-env NODE_ENV=development webpack --config webpack.config.js && cp ./src/index.php ./dist/",
"b_pro": "cross-env NODE_ENV=production webpack --config webpack.config.js && cp ./src/index.php ./dist/",
webpack.config.js 文件包含下面两句:
const isDev = process.env.NODE_ENV === 'development';
const config = {
mode: isDev ? 'development' : 'production',
……
}
七、 清理目标文件夹
手动清理目标文件夹很不方便,所以引入 clean-webpack-plugin 插件进行清理。
const clean = require('clean-webpack-plugin');
……
new clean(['dist']),
……
或者,在脚本里加入 linux 命令清理。(未尝试)
八、 vue 中 $emit 无法触发问题
事件名要小写。
九、 json 中 html 标签问题
因为需要将搜索的关键字在结果中高亮,所以在 php 中对结果字符串进行替换:
$result_array[$key]['d_poetry'] = str_replace($name,"<span style = \"color: red;\">".$name."</span>",$result_array[$key]['d_poetry']);
但是并没有达到预期中的结果。无论检查多少遍,尝试多少遍都不行。于是,另写一个测试文件。
<?php $text = "一"; $obj = new StdClass(); $obj -> text = "这是一行文字"; $str = "<span style=\" color:red\" >".$text."</span>"; $obj -> text = str_replace($text,$str,$obj -> text); echo $obj -> text; echo "<br>" echo json_encode($obj);
结果是什么呢?
qq 浏览器如下:
额,算了,过程比较曲折,直接说结果吧。
将 json_encode($obj) 改成 json_encode($obj,JSON_HEX_TAG)。
参考:# json返回数据中带有html标签的输出
十、 url 中文转码问题
在发送请求的时候,ie 浏览器使用的不是 utf-8 编码,而是系统本地编码,比如 gbk。这样一来,中文的传输就成了问题。因为后台是 utf-8 编码。所以,我们需要对中文进行转码。
编码:
js: url = encodeURI(encodeURI(url));
解码:
php: url = urldecode(url);
部分 php 函数:
- is_array()
- count()
- file_get_contents()
- mysqli_connect()
- mysqli_query()
- mysqli_select()
- mysqli_num_rows()
- mysqli_fetch_all()
- mysqli_free_result()
- mysqli_close()
- isset()
- is_numeric()
- substr()
- urldecode()
- unset()
- array_unique()
- array_rand()
- str_replace()
- ceil()
成品
链接:诗词