Laravel Npm Node
发布时间:2018-11-20, 17:57:43 分类:PHP | 编辑 off 网址 | 辅助
图集1/1
正文 753字数 3,298,758阅读
[ Laravel 5.4 文档 ] 前端 —— 编译资源(Laravel Mix)
安装 Node
https://nodejs.org/en/download/
在开始接触 Mix 之前,必须首先确保 Node.js 和 NPM 在机器上已经安装:
node -v
npm -v
Run code
Cut to clipboard
Laravel Mix
接下来,需要安装 Laravel Mix,在新安装的 Laravel 根目录下,你会发现有一个 package.json 文件。该文件包含你所需要的一切,和 composer.json 类似,只不过是用来定义 Node 依赖而非 PHP 依赖,你可以通过运行如下命令来安装需要的依赖:
npm install
Run code
Cut to clipboard
如果你正在 Windows 系统上开发,需要在运行 npm install 命令时带上 --no-bin-links:
npm install --no-bin-links
Run code
Cut to clipboard
运行 Mix
Mix 是位于 Webpack 顶层的配置层,所以要运行 Mix 任务你只需要在运行包含在默认 package.json 文件中的其中某个 NPM 脚本即可:
// 运行所有 Mix 任务...
npm run dev
// 运行所有 Mix 任务并减少输出...
npm run production
Run code
Cut to clipboard
监控前端资源改变
npm run watch 命令将会持续在终端运行并监听所有相关文件的修改,Webpack将会在发现修改后自动重新编译资源文件:
npm run watch
Run code
Cut to clipboard
(支付宝)给作者钱财以资鼓励 (微信)→
有过 20 条评论 »
在使用webpack2.x打包时,出现下面报错(Unexpected token name «i», expected punc «;»): ERROR in app.js from UglifyJs Unexpected token name «i», expected punc «;» [app.js:9461,13] 定位到的报错是: function oneOf (value, validList) { for (let i = 0; i < validList.length; i++) {//此行报错 if (value === validList[i]) { return true; } } return false; } 看样子是UglifyJs压缩插件在遇到es6语法时出错了。但是项目中自己写的代码是有用babel编译的,上面报错的代码应该是来自vue的库。为什么这些代码没有经过babel编译后才执行UglifyJs压缩呢?
修改
node_modules\laravel-mix\setup\webpack.config.js
注释掉
{ test: /\.jsx?$/, //exclude: /(node_modules|bower_components)/, loader: 'babel-loader' + Mix.babelConfig() },
碰到的问题(Couldn't find preset "es2015" relative to directory)
MODULE BUILD FAILED: ERROR: COULDN’T FIND PRESET “ES2015” RELATIVE TO DIRECTORY
遇到这个问题的时候我们需要安装 babel-preset-es2015
npm install babel-preset-es2015 --save-dev
/*{ test: /iview.src.*?js$/, loader: 'babel-loader' },*/ { test: /\.jsx?$/, //exclude: /(node_modules|bower_components)/, loader: 'babel-loader' + Mix.babelConfig() }
{ "private": true, "scripts": { "serve": "php artisan serve", "apidoc": "apidoc -i app/Http/Controllers/Api/v2 -o public/docs", "ide-helper": "php artisan ide-helper:generate", "git-push": "git add -A && git commit -m 'no msg' && git push --progress 'origin' master:master", "dev": "npm run development", "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", "watch-poll": "npm run watch -- --watch-poll", "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", "prod": "npm run production", "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", "fix-memory-limit": "cross-env LIMIT=8096 increase-memory-limit" }, "devDependencies": { "axios": "^0.15.3", "babel-loader": "^7.1.1", "babel-preset-es2015": "^6.24.1", "bootstrap-sass": "^3.3.7", "cross-env": "^3.2.4", "css-loader": "^0.26.4", "element-ui": "^1.3.7", "fastclick": "^1.0.6", "increase-memory-limit": "^1.0.6", "jquery": "^3.2.1", "laravel-mix": "^0.12.1", "lodash": "^4.17.4", "stylus": "^0.54.5", "stylus-loader": "^3.0.1", "vue": "^2.4.2", "vue-loader": "^11.3.4", "vue-router": "^2.7.0", "vue-style-loader": "^2.0.5", "vue-template-compiler": "^2.4.2" }, "dependencies": { "chart.js": "^2.6.0", "iview": "^2.0.0", "vant": "^0.12.3", "vue-chartjs": "^2.7.2", "vue-github-badge": "^1.0.1", "vue-html5-editor": "^1.1.1", "vue-image-crop-upload": "^2.1.3", "vue-quill-editor": "^2.2.6", "vue-social-share": "^0.0.3", "vuex": "^3.0.1" } }
var mix = require('laravel-mix'); var production=0; //282216 //284050 // npm run watch // npm run production if(production) Mix.babelConfig={ babelrc: false, presets: [ ['es2015'], ], }; //复制图片资源 //mix.copy('resources/assets/images', 'public/images'); //生成vue页面js mix //.js('resources/assets/js/app.js', 'public/js/app.js') .js('resources/assets/js/admin/main.js', 'public/js/admin.js') //.js('resources/assets/js/api/main.js', 'public/js/api.js') //.js('resources/assets/js/business/main.js', 'public/js/business.js') .js('resources/assets/js/city/main.js', 'public/js/city.js'); //生成bootstrap样式文件 //mix.sass('resources/assets/sass/app.scss', 'public/css'); //配置webpack mix.webpackConfig({ output: { // 路由懒加载文件路径 chunkFilename: "js/build/[id].js?[hash:8]" }, module: { rules: [{ // 图片资源保存路径规则 test: /\.(png|jpe?g|gif)$/, loaders: [ { loader: 'file-loader', options: { name: path => { // 自定义部分 try { if (/\/resources\/assets\//.test(path)) { var file = path.substring(path.indexOf('/resources/assets/') + '/resources/assets/'.length); if (file) { if (file.substring(0, 3) === 'js/') file = 'pages/' + file.substring(3); if (file.substring(0, 7) === 'images/') file = file.substring(7); return 'images/' + file + '?[hash:8]' } } } catch (e) { } // 系统定义部分 if (!/node_modules|bower_components/.test(path)) { return 'images/[name].[ext]?[hash:8]'; } return 'images/vendor/' + path .replace(/\\/g, '/') .replace( /((.*(node_modules|bower_components))|images|image|img|assets)\//g, '' ) + '?[hash:8]'; }, publicPath: mix.config.options.resourceRoot } } ] }, { // 字体资源保存路径规则 test: /\.(woff2?|ttf|eot|svg|otf)$/, loader: 'file-loader', options: { name: path => { // 自定义部分 try { if (/\/resources\/assets\//.test(path)) { var file = path.substring(path.indexOf('/resources/assets/') + '/resources/assets/'.length); if (file) { if (file.substring(0, 3) === 'js/') file = 'pages/' + file.substring(3); if (file.substring(0, 7) === 'fonts/') file = file.substring(7); return 'fonts/' + file + '?[hash:8]' } } } catch (e) { } // 系统定义部分 if (!/node_modules|bower_components/.test(path)) { return 'fonts/[name].[ext]?[hash:8]'; } return 'fonts/vendor/' + path .replace(/\\/g, '/') .replace( /((.*(node_modules|bower_components))|fonts|font|assets)\//g, '' ) + '?[hash:8]'; }, publicPath: mix.config.options.resourceRoot } }] } });
语句二: SELECT * FROM users AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(userId) FROM `users`)-(SELECT MIN(userId) FROM users))+(SELECT MIN(userId) FROM users)) AS userId) AS t2 WHERE t1.userId >= t2.userId ORDER BY t1.userId LIMIT 1 执 行该sql语句,用时0.031s,效率非常好。当把”LIMIT 1“改为了”LIMIT 100“ 随机取一百条记录,用时0.048s。可是就在此时问题出现了,发现结果好像不是随机的。为了验证结果,又执行了N次,的确不是随机的。问题出现 在”ORDER BY t1.userId“这里,按userId排序了。随机取一条记录还是不错的选择,多条就不行了啊。 ---------分隔线------------------------------------ 语句三: SELECT * FROM users WHERE userId >= ((SELECT MAX(userId) FROM users)-(SELECT MIN(userId) FROM users)) * RAND() + (SELECT MIN(userId) FROM users) LIMIT 1 执行该sql语句,用时0.039s,效率也是非常好。接着把”LIMIT 1“改为了”LIMIT 10000“,用时0.063s。经过多次验证,得出的结果都是随机的。 ---------分隔线------------------------------------ 结论:随机获得一条记录,语句二是相当不错的选择,采用JOIN的语法比直接在WHERE中使用函数效率还是要高一些的。语句三也不错,随机获得多条记录的首选。
npm install --no-bin-links npm install --save-dev cross-env npm install node-sass 先ctrl+d在ctrl+c 就能完全退出
Unexpected token name «i», expected punc «;» [./~/_iview@2.14.3@iview/src/utils/assist.js:5,0][js/build/4.js?590e6c36:1463,13]
error
js/build/5.js?590e6c36 from UglifyJs
Unexpected token name «i», expected punc «;» [./~/_iview@2.14.3@iview/src/utils/assist.js:5,0][js/build/5.js?590e6c36:1463,13]
修改webpack.mix.js文件添加
var mix = require('laravel-mix'); Mix.babelConfig={ babelrc: false, presets: [ ['es2015'], ], };
$ npm install --save-div babel-preset-es2015 $ cnpm install --save-div babel-preset-es2015
用webpack的uglifyJS压缩ES6代码报错webpack uglifyjs报错UglifyJs Unexpected token name «i», expected punc «;»
iview table的render()函数基本的用法
render:(h,params)=>{ return h('div', {style:{width:'100px',height:'100px',background:'#ccc'}}, '地方') }
render:(h,params)=>{ return h('div',{style:{width:'100px',height:'100px',background:'#ccc'}},[h('p','内容2')],'内容1') }
render:(h, params) => { return h('div',[ h('div',{style:{float:'left',width:'50px',height:'50px',background:'#ccc'}},[h('p','内容2')]), h('div',{style:{float:'left',width:'50px',height:'50px',background:'#fc1'}},[h('p','内容2')]) ]) }
on: { click: () => {console.log('ffff')}, mouseover:() => { console.log('bbb')} }
{ title: '操作', align:'center', width:130, render:(h, params) => { let status = params.row.Status; //0:空闲 1:游戏 2:未上线 if (status===0){ return h('Button','空闲中') }; if (status===1){ return h('Button','游戏中')}; if (status===2){ return ""} //未上线时不显示} }
iview中render函数监听事件
iview的table中添加datepicker
在组件中嵌套组件,如果需要监听子组件的自定义事件,
应该使用render中的
on:{ 'on-change' () => { console.log('这里会触发子组件的事件') } }
{ title: '发布时间', key: 'pubdate', sortable: true, width: 280, render: (h, params) => { return h('div', [ h('DatePicker', { props: { type: 'datetime', format: 'yyyy-MM-dd HH:mm', placeholder: '选择日期和时间', value: params.row.pubdate }, style: { marginRight: '5px' }, on: { 'on-change': (val) => { console.log('发布时间1') } } }) ]) } }
rm -rf node_modules rm package-lock.json npm cache clear --force npm install
npm install --save-dev cross-env
https://www.npmjs.com/package/cross-env
能够提供一个设置环境变量的scripts,让你能够以unix方式设置环境变量,然后在windows上也能兼容运行。
在NODE_ENV=xxxxxxx前面添加cross-env就可以了。
npm install --save glob
node npm 本地服务?
npm ERR! asyncWrite is not a function
laravel Composer
devDependencies
shouldOverrideUrlLoading网址错误
Android apk启动图片
阻止 android webview 中的链接跳出APP(即跳转到系统浏览器)
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { view.loadUrl(request.getUrl().toString()); return true; }
tuike.java
package com.example.administrator.myapplication; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.KeyEvent; import android.webkit.WebView; import android.webkit.WebViewClient; public class tuike extends AppCompatActivity { private WebView webview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); //实例化WebView对象 webview = new WebView(this); //设置WebView属性,能够执行Javascript脚本 webview.getSettings().setJavaScriptEnabled(true); try { //设置打开的页面地址 webview.loadUrl("http://lizhenqiu.com/"); } catch(Exception ex) { ex.printStackTrace(); } webview.setWebViewClient(new WebViewClient() { public boolean shouldOverrideUrlLoading(WebView view, String url) { // 重写此方法表明点击网页里面的链接还是在当前的webview里跳转,不跳到浏览器那边 view.loadUrl(url); return true; } }); setContentView(webview); } // 按键响应,在WebView中查看网页时,按返回键的时候按浏览历史退回,如果不做此项处理则整个WebView返回退出 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) { // 返回键退回 webview.goBack(); return true; } return super.onKeyDown(keyCode, event); } }
g_tuike.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".tuike"> <WebView android:id="@+id/Toweb" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </android.support.constraint.ConstraintLayout>
strings.xml
<resources> <string name="app_name">lizhenqiu.com</string> </resources>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.administrator.myapplication"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".tuike"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.INTERNET"/> </manifest>
Android webview loadUrl() 禁止弹出系统浏览器代码
<?php // 生成一个PHP数组 $data = array(); $data['a'] = 'test'; $data['b'] = 'bbb'; // 把PHP数组转成JSON字符串 $json_string = json_encode($data); // 写入文件 file_put_contents('test.json', $json_string);
<?php // 从文件中读取数据到PHP变量 $json_string = file_get_contents('test.json'); // 把JSON字符串转成PHP数组 $data = json_decode($json_string, true); // 显示出来看看 var_dump($data);
1、TypeError: gfs.gracefulify is not a function at C:\Program Files\nodejs\node_modules\npm\lib\npm.js:18:16 at Object.<anonymous> (C:\Program Files\nodejs\node_modules\npm\lib\npm.js:483:3) at Module._compile (module.js:399:26) 解决:这是由于node modules里的graceful-fs包有问题,去github下载本包,覆盖node_modules文件夹下的graceful-fs目录即可解决,注意版本 2、Error: Cannot find module 'debug' at Function.Module._resolveFilename (module.js:327:15) at Function.Module._load (module.js:278:25) at Module.require (module.js:355:17) at require (internal/module.js:13:17) 解决:这是由于本人引用了debug模块,而未成功安装的缘故,使用npm install debug 解决 3、TypeError: glob.hasMagic is not a function at rimraf (C:\Program Files\nodejs\node_modules\npm\node_modules\rimraf\rimraf.js:59:36) at exit (C:\Program Files\nodejs\node_modules\npm\lib\utils\error-handler.js:83:8) at process.errorHandler (C:\Program Files\nodejs\node_modules\npm\lib\utils\error-handler.js:487:3) at emitOne (events.js:78:13) at process.emit (events.js:170:7) at process._fatalException (node.js:237:26) 解决:办法与1一致
chmod -R 777 /home/user 注:表示将整个/home/user目录与其中的文件和子目录的权限都设置为rwxrwxrwx
Ctrl-D
find . -mindepth 2 -name '.svn' -exec rm -rf '{}' \;
ll -a显示当前目录所有文件、文件夹的详细信息,包括权限、大小、用户、组等
ls -a显示当前目录下所有文件、文件夹的简略信息,只有文件(夹)的名称,以"."开头的都是隐藏文件。
l.(这是个命令别名,实际命令为ls -d .* --color=auto)显示当前目录下的所有隐藏文件,只显示名称,不显示详情
svn st | grep '^\?' | tr '^\?' ' ' | sed 's/[ ]*//' | sed 's/[ ]/\\ /g' | xargs svn add
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <form name="form1"> <select name="country" onChange="getCity()" > <option value="0">请选择所在的国家</option> <option value="1">中国</option> <option value="2">美国</option> <option value="3">英国</option> <option value="4">意大利</option> </select> <select name="city"> <option value="0">请选择所在的城市 </option> </select> </form> </body> <script type="text/javascript"> //定义一个二维数组 var city=[ ["北京","上海","广州","深圳"], ["华盛顿","纽约","旧金山","西雅图"], ["剑桥","伦敦","苏格兰地区","北爱尔兰地区"], ["罗马","米兰","威尼斯","都灵"] ]; function getCity(){ var sltCountry=document.form1.country; //获得国家下拉框的对象 var sltCity=document.form1.city; //获得城市下拉框的对象 var country=city[sltCountry.selectedIndex-1]; //得到对应国家的城市数组 sltCity.length=1; //清空城市下拉框,仅留提示选项。 //通过for循环,将城市中的值填充到城市下拉框中 for(var i=0;i<country.length;i++){ sltCity[i+1]=new Option(country[i],country[i]); } } </script> </html>
假设将A仓库的数据转移到B仓库 A位置:/svndata/A B位置:/svndata/B 不能直接将A仓库重命名为B,或将A复制得到一个复本,再将复本命名为B 使用svnadmin dump & svnadmin load 创建B仓库(如果B不存在) svnadmin create /svndata/B 得到A仓库.dump文件A.dump svnadmin dump /svndata/A > A.dump 将A.dump 加载到B仓库 svnadmin load /svndata/B < A.dump 使用dump&load方法只将A管理的文件复制到B中,但是A的配置信息(密码等)没有被复制到B中
cp -pR svn co file:///www/web/svn_api_gengdian_net/ /www/web/api_gengdian_net svn st | awk '{if ($1 == "?") {print $2} }' | xargs svn add mv /www/web/api_gengdian_net_20181128/api_gengdian_net /www/web/api_gengdian_net svn commit -m “提交当前目录下的全部在版本控制下的文件“ * ( *表示全部文件 ) svn commit -m "20181128" * [general] #匿名访问的权限,可以是read,write,none,默认为read anon-access=none #使授权用户有写权限 auth-access=write #密码数据库的路径 password-db=passwd #访问控制文件 authz-db=authz #认证命名空间,subversion会在认证提示里显示,并且作为凭证缓存的关键字 realm=/www/web/svn_api_gengdian_net svn一次性add/delete所有文件 Linux命令行下,svn add 一次性批量上传 命令行下操作svn没有使用界面形式的TortoiseSVN直观,但是不管怎样,命令行下操作svn还是有它的有点,如果你碰到一次需要svn add许多个文件怎么办?下面的命令可以帮助你解决这个问题 一次性增加所有新增的文件到svn库: svn st | awk '{if ($1 == "?") {print $2} }' | xargs svn add 一次性从svn库删除所有需要删除的文件 svn st | awk '{if ($1 == "!") {print $2}}' | xargs svn rm 最后直接提交你的修改(注意:这里的-F 代表上传的注释从comment.txt文件读取) svn ci -F comment.txt 将以上三个命令写成一个脚本(此时svn st应该替换成svn st yourPath) ,就可以一键上传svn了
输入npm install 或 cnpm install
//exclude: /node_modules/, //只要把这个注释掉就可以了。就会先进行es5转换,然后在打包压缩
ERROR in build.js from UglifyJs Unexpected token operator «=», expected punc «,»
定位到的报错是: function oneOf (value, validList) { for (let i = 0; i < validList.length; i++) {//此行报错 if (value === validList[i]) { return true; } } return false; }
看样子是UglifyJs压缩插件在遇到es6语法时出错了。但是项目中自己写的代码是有用babel编译的,上面报错的代码应该是来自vue的库。为什么这些代码没有经过babel编译后才执行UglifyJs压缩呢?
ERROR in js/backstage.js from UglifyJs Unexpected token name «i», expe
iview 按需加载报错 ERROR in js/backstage.js from UglifyJs Unexpected token name «i», expected punc «;»
//webpack.config.js { test: /iview.src.*?js$/, loader: 'babel-loader' }
npm watch --poll
你可以在执行命令的后面接一个&命令就会在后台运行了。完整命令:
npm run watch-poll &
如果已经直接执行了npm run watch-poll,可以直接按ctrl + z,将程序挂到后台,然后会看到一个任务号,如:[1]+ Stopped npm run watch-poll,再执行:bg 1就相当于上述第一条解决办法。 [1]这方括号里的1就是任务号
<Select v-model="device.type" :label-in-value="true" @on-change="v=>{ setOption(v,'type')}"> <Option v-for="item in deviceTypeList" :value="item.value" :key="item">{{ item.label }}</Option> </Select>
我们在默认的函数内放一个匿名函数,这个函数执行一个我们定义好的`methods`传2个参数,一个是默认函数的参数,也就是获取点击选择的那个值,另一个函数就是我们需要用来判断的参数。
//setOption setOption(value,type){ console.log(value); console.log(type); }
清空DatePicker(日期选择器)的方法: this.$refs.element.handleClear() 清空TimePicker(时间选择器)的方法: this.$refs.element.handleClear() 清空Select组件的方法: this.$refs.element.clearSingleSelect() 清空Table组件的方法: this.$refs.element.selectAll(flase) 清空input组件的方法: 直接让绑定的变量等于空
记住用@on-change 不要用‘:’ 回造成死循环