澳门新萄京官方网站-www.8455.com-澳门新萄京赌场网址

澳门新萄京官方网站:webpack搭建vue最全分析,实

2019-12-12 作者:澳门新萄京赌场网址   |   浏览(146)

前端基础进阶(15):详解 ES6 Modules

2017/07/02 · JavaScript · es6

原文出处: 波同学   

澳门新萄京官方网站 1

E S 6 M O D U L E S

对于新人朋友来说,想要自己去搞定一个ES6开发环境并不是一件容易的事情,因为构建工具的学习本身又是一个非常大的方向,我们需要花费不少的时间才能掌握它。

好在慢慢的开始有大神提供了一些非常简单易懂,学习成本非常低的解决方案来帮助大家学习。create-react-app就是这些解决方案中,个人认为最简单易懂的一种方式。

所以在学习ES6 modules之前,先跟大家介绍一下create-react-app的安装与使用。

尽管create-react-app的目的是用于开发react程序,但是我们仅仅只用来学习ES6是再合适不过了。当然你也可以借助vue-cli来学习,同样十分简单。

一、安装准备工作 ( 本教程在windows下安装完成 )

    1、安装 Node.js ( 传送门:Node.js 的安装)

        官方下载 NodeJs 对应系统安装包,执行安装即可,打开cmd  执行 node -v 查看 node 版本确认 node 是否安装成功,执行 npm -v  查看 npm 版本

    2、将 npm 改成 cnpm 以满足国内翻墙不易的悲剧,在 node.js 安装笔记中也已经介绍

全局安装的话可执行该命令:

    npm install -g cnpm --registry=

概述

历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。其他语言都有这项功能,比如 Ruby 的require、Python 的import,甚至就连 CSS 都有@import,但是 JavaScript 任何这方面的支持都没有,这对开发大型的、复杂的项目形成了巨大障碍。

在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。

ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。

下面介绍一下es6的简单使用。

原标题:vue-cli webpack搭建vue最全分析

1、确保自己的本地环境已经安装了node与npm

通常安装的方式就是去node的官方网站下载安装,在安装node的时候,npm也会一起被安装。

下载地址:

二、使用脚手架创建项目(推荐)

     create-react-app 是来自于 Facebook,通过该命令我们无需配置就能快速构建 React 开发环境。  create-react-app 自动创建的项目是基于 Webpack ES6 。React 官网

    执行以下命令创建项目,其中 my-app 为你的项目名称,npm start  为启动服务命令:

$ cnpm install -g create-react-app

$ create-react-app jiaocheng

$ cd my-app/

$ npm start

澳门新萄京官方网站 2

安装界面

澳门新萄京官方网站 3

安装成功后的项目目录

 node_modules: 这里面包含了react项目中会用到的一些组件,install的时候下载下来的,你可以进去看看,有一些如base64之类的我们可能会用到的组件;

public:里面包含了我们项目中的启动页面,react比较适合单页面项目应用开发,所以暂时只包含一个index.html,并且这也是react工程的入口页面,入口页面怎么理解,就是你启动项目后,打开的首页,第一眼呈现的那个页面;

src:里面包含了一些我们自己使用的js文件,css文件,img文件等等,但你打开src文件夹你会发现很混乱,不要管什么app.js,你就看到index.js即可,系统默认将index.html对准了index.js,index.js也就是我们的入口js,他和index.html所对应。

使用 npm start 命令启动服务后,则会自动打开项目主页  ,结果如下图所示:

澳门新萄京官方网站 4

启动服务过程

澳门新萄京官方网站 5

启动服务后的主页

自己配置过webpack的同学可能会发现,“好像少点什么?”,create-react-app脚手架工具对webpack配置文件进行了隐藏,为了能够顺利的搭建antd-mobile,我们需要让配置文件“显示出来”,命令如下:

npm run eject

小提示:运行前您可能需要按CTRL C退出启动的项目

运行后,发现它会执行一系列安装..出现如下结果说明成功完成:

Running npm install...

added 117 packages and updated 1 package in 14.894s

Ejected successfully!

Please consider sharing why you ejected in this survey:

npm run eject执行后项目中多出了一个叫config的文件夹具体如下:

澳门新萄京官方网站 6

config 目录文件

为了阅读这篇文章的同学后面少些坑,我们顺手解决下打包路径的问题。用create-react-app脚手架搭建的react项目使用 npm run build 之后生成的打包文件只能在根目录访问,这样放在服务器目录就访问不到了,为了你们不要和我一样打包后在哭着百度解决方案,在这里一并放出:

config文件夹下面找到paths.js文件,打开后大约在34~39行前后有如下代码:

function getServedPath(appPackageJson) {

  const publicUrl = getPublicUrl(appPackageJson);

  const servedUrl =envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : '/');

  return ensureSlash(servedUrl, true);

}

将这句修改为:(仔细看,最后面的"/"前面加了一个".")

const servedUrl =envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : './');

下面进行LESS CSS预处理器配置,antd-mobile依赖LESS模块,不安装和配置好,样式是不会起作用的,在项目根目录运行如下命令:

cnpm install

less less-loader

--save-dev

这里面注意下 less 和 less-loader 都是需要安装的,不然在启动项目时就会报Error in Cannot find module 'less' 原因是npm @ 3不能再解析peerDependencies了,OK安装后,我们还要着手配置下,打开config文件夹中的webpack.config.dev.js文件,搜索“exclude:”  找到大概这么一行:

  exclude: [/.js$/, /.html$/, /.json$/],

loader: require.resolve('file-loader')

... ...

在exclude: 后面的数组中加入一项   /.less$/   这行变为

exclude: [/.js$/, /.html$/, /.json$/,/.less$/],

然后在loders中加入一段:

//新增less支持

{

    test: /.less$/,

    use: [

      require.resolve('style-loader'),

      require.resolve('css-loader'),

      {

        loader: require.resolve('postcss-loader'),

        options: {

          ident: 'postcss', //

          plugins: () => [

            pxtorem({

              rootValue: 100,

              propWhiteList: [],

            }),

            autoprefixer({

              browsers: ['last 2 versions', 'Firefox ESR', '> 1%', 'ie >= 8', 'iOS >= 8', 'Android >= 4'],

            }),

          ],

        },

      },

      {

        loader: require.resolve('less-loader'),

        options: {

          modifyVars: { "@primary-color": "#1DA57A" },

        },

      },

    ],

},

搞不清楚loders结构的同学,找下如下代码,加在其最后一个花括号下方即可:

          {

            test: /.(js|jsx|mjs)$/,

            include: paths.appSrc,

            loader: require.resolve('babel-loader'),

            options: {

              plugins: [

                      ['import', { libraryName: 'antd-mobile', style: true }],

                    ],

澳门新萄京官方网站:webpack搭建vue最全分析,实战教程。              // This is a feature of `babel-loader` for webpack (not Babel itself).

              // It enables caching results in ./node_modules/.cache/babel-loader/

              // directory for faster rebuilds.

              cacheDirectory: true,

            },

  },

一模一样的方式在 config文件夹里的webpack.config.prod.js里在做一遍,这步配置就完成了。接下来安装babel-plugin-import ,然后就可以按需加载组件了,并且它会自动关联css样式,无需单独引入。我们只需要这样引入一次即可:import { Button } from 'antd-mobile';详细的见官网吧。

cnpm install babel-plugin-import --save-dev

安装完毕后,在webpack.config.dev.js中找到这段代码按如下配置:

{

    test: /.(js|jsx)$/,

    include: paths.appSrc,

    loader: require.resolve('babel-loader'),

    options: {

      plugins: [

        ['import', { libraryName: 'antd-mobile', style: true }],

      ],

      // This is a feature of `babel-loader` for webpack (not Babel itself).

      // It enables caching results in ./node_modules/.cache/babel-loader/

      // directory for faster rebuilds.

      cacheDirectory: true,

    },

},

至此,Create-React-App脚手架搭建antd-mobile并进行按需加载的开发环境配置完毕!

1. 引入模块

首先在根目录的src文件夹下创建一个test.js和index.js,在test.js中我们随便干点什么简单的事情即可。

// src/test.js
console.log('first module');

 

在index.js中通过import引入test.js,这是我们要学会的第一个语法

// src/index.js
import test from './test'

console.log(test);

 

  • import表示引入一个模块,
  • test 我们暂时理解为引入模块的名字,
  • from表示从哪里引入
  • ./test为./test.js的简写,表示将要引入模块的路径

引入这个动作执行时,test.js中的代码也执行了。由于在test.js中并没有对外暴露任何接口,因此index.js中的test为一个空对象,那么对外暴露接口的方式,则是我们要学习的第二个语法。

一、vue-cli介绍

vue-cli是一个基于nodeJs、用于快速搭建vue项目的 脚手架。

二、vue-cli安装、更新

安装过nodeJs 、cnpm 后,全局安装vue-cli(以后其他项目可直接使用):

cnpm install -g vue-cli

更新:

cnpm update vue-cli

查看安装成功否(有版本号就是成功,V大写)

vue -V

查看npm注册表里vue-cli版本号:

cnpm view vue-cli

三、vue-cli 使用

安装过webpack 、vue-cli后,可以开始搭建vue项目:

vue init webpack <Project Name>

eg:右击Git Base Here(如果你没有用git ,你也可以按住shift键右击选择“在此处打开命令窗口”,或者 cmd :cd project/lfxProject),如图:

澳门新萄京官方网站 7or

ps:ESLint(一个java代码检测工具)、unit tests(单元测试)、Nightwatch(一个e2e用户界面测试工具)。

澳门新萄京官方网站:webpack搭建vue最全分析,实战教程。四、项目完成

项目结构如下:

澳门新萄京官方网站 8

各文件作用解析,如下:

1、build文件夹:

build文件夹的结构:

澳门新萄京官方网站 9

(1)build.js

'use strict'

require('./check-versions')() //调用版本检查

process.env.NODE_ENV = 'production' //将环境配置为生产环境

const ora = require('ora') //npm包 loading插件

const rm = require('rimraf') //npm包 用于删除文件

const path = require('path')//npm包 文件路径工具

const chalk = require('chalk')//npm包 在终端输出带颜色的文字

const webpack = require('webpack')//引入webpack.js

const config = require('../config')//引入配置文件

const webpackConfig = require('./webpack.prod.conf')//引入生产环境配置文件

// 在终端显示loading效果,并输出提示

const spinner = ora('building for production...')

spinner.start()

//先递归删除dist文件再生成新文件,避免冗余

rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {

if (err) throw err

webpack(webpackConfig, (err, stats) => {

spinner.stop()

if (err) throw err

process.stdout.write(stats.toString({

colors: true,

modules: false,

children: false,

chunks: false,

chunkModules: false

}) 'nn')

if (stats.hasErrors()) {

console.log(chalk.red(' Build failed with errors.n'))

process.exit(1)

}

console.log(chalk.cyan(' Build complete.n'))

console.log(chalk.yellow(

' Tip: built files are meant to be served over an HTTP server.n'

' Opening index.html over file:// won't work.n'

))

})

})

ps:require/export是一种nodeJs(commonJs规范)的依赖注入的方法,import/export是ES6语法,用于引入模块,在nodeJs中使用的ES6语法最终会使用babel工具(babel-loader)转化为ES5

(2)check-version.js:检测node和npm的版本,实现版本依赖

'use strict'

const chalk = require('chalk')

const semver = require('semver')//检查版本

const packageConfig = require('../package.json')

const shell = require('shelljs')//shelljs 模块重新包装了 child_process,调用系统命令更加方便

function exec (cmd) {//返回通过child_process模块的新建子进程,执行 Unix 系统命令后转成没有空格的字符串

return require('child_process').execSync(cmd).toString().trim()

}

const versionRequirements = [

{

name: 'node',

currentVersion: semver.clean(process.version),//使用semver格式化版本

versionRequirement: packageConfig.engines.node //获取package.json中设置的node版本

}

]

if (shell.which('npm')) {

versionRequirements.push({

name: 'npm',

currentVersion: exec('npm --version'),// 自动调用npm --version命令,并且把参数返回给exec函数,从而获取纯净的版本号

versionRequirement: packageConfig.engines.npm

})

}

module.exports = function () {

const warnings = []

for (let i = 0; i < versionRequirements.length; i ) {

const mod = versionRequirements[i]

//若版本号不符合package.json文件中指定的版本号,就报错

if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {

warnings.push(mod.name ': '

chalk.red(mod.currentVersion) ' should be '

chalk.green(mod.versionRequirement)

)

}

}

if (warnings.length) {

console.log('')

console.log(chalk.yellow('To use this template, you must update following to modules:'))

console.log()

for (let i = 0; i < warnings.length; i ) {

const warning = warnings[i]

console.log(' ' warning)

}

console.log()

process.exit(1)

}

}

(3)utils.js:utils是工具的意思,是一个用来处理css的文件,这个文件包含了三个工具函数:

  • 生成静态资源的路径
  • 生成 ExtractTextPlugin对象或loader字符串
  • 生成 style-loader的配置

var path = require('path')// node自带的文件路径工具

var config = require('../config')// 配置文件

var ExtractTextPlugin = require('extract-text-webpack-plugin')// 提取css的插件

/** @method assertsPath 生成静态资源的路径(判断开发环境和生产环境,为config文件中index.js文件中定义assetsSubDirectory)

* @param {String} _path 相对于静态资源文件夹的文件路径

* @return {String} 静态资源完整路径

*/

exports.assetsPath = function (_path) {

var assetsSubDirectory = process.env.NODE_ENV === 'production'

? config.build.assetsSubDirectory

: config.dev.assetsSubDirectory

//nodeJs path提供用于处理文件路径的工具;path.posix提供对路径方法的POSIX(可移植性操作系统接口)特定实现的访问(可跨平台); path.posix.join与path.join一样,不过总是以 posix 兼容的方式交互

return path.posix.join(assetsSubDirectory, _path)

}

/**@method cssLoaders 生成处理css的loaders配置,使用css-loader和postcssLoader,通过options.usePostCSS属性来判断是否使用postcssLoader中压缩等方法

* @param {Object} option = {sourceMap: true,// 是否开启 sourceMapextract: true // 是否提取css}生成配置

* @return {Object} 处理css的loaders配置对象

*/

exports.cssLoaders = function (options) {

options = options || {}

var cssLoader = {

loader: 'css-loader',

options: {

minimize: process.env.NODE_ENV === 'production',

sourceMap: options.sourceMap

}

}

/**@method generateLoaders 生成 ExtractTextPlugin对象或loader字符串

* @param {Array} loaders loader名称数组

* @return {String|Object} ExtractTextPlugin对象或loader字符串

*/

function generateLoaders (loader, loaderOptions) {

var loaders = [cssLoader]

if (loader) {

loaders.push({

loader: loader '-loader',

options: Object.assign({}, loaderOptions, {

sourceMap: options.sourceMap

})

})

}

// ExtractTextPlugin提取css(当上面的loaders未能正确引入时,使用vue-style-loader)

if (options.extract) {// 生产环境中,默认为true

return ExtractTextPlugin.extract({

use: loaders,

fallback: 'vue-style-loader'

})

} else {//返回vue-style-loader连接loaders的最终值

return ['vue-style-loader'].concat(loaders)

}

}

return {

css: generateLoaders(),//需要css-loader 和 vue-style-loader

postcss: generateLoaders(),//需要css-loader、postcssLoader 和 vue-style-loader

less: generateLoaders('less'),//需要less-loader 和 vue-style-loader

sass: generateLoaders('sass', { indentedSyntax: true }),//需要sass-loader 和 vue-style-loader

scss: generateLoaders('sass'),//需要sass-loader 和 vue-style-loader

stylus: generateLoaders('stylus'),//需要stylus-loader 和 vue-style-loader

styl: generateLoaders('stylus')//需要stylus-loader 和 vue-style-loader

}

}

/**@method styleLoaders 生成 style-loader的配置

* @param {Object} options 生成配置

* @return {Array} style-loader的配置

*/

exports.styleLoaders = function (options) {

var output = []

var loaders = exports.cssLoaders(options)

//将各种css,less,sass等综合在一起得出结果输出output

for (var extension in loaders) {

var loader = loaders[extension]

output.push({

test: new RegExp('\.' extension '$'),

use: loader

})

}

return output

}

(4)vue-loader.conf.js:处理.vue文件,解析这个文件中的每个语言块(template、、style),转换成js可用的js模块。

'use strict'

const utils = require('./utils')

const config = require('../config')

const isProduction = process.env.NODE_ENV === 'production'

//生产环境,提取css样式到单独文件

const sourceMapEnabled = isProduction

? config.build.productionSourceMap

: config.dev.cssSourceMap

module.exports = {

loaders: utils.cssLoaders({

sourceMap: sourceMapEnabled,

extract: isProduction

}),

cssSourceMap: sourceMapEnabled,

cacheBusting: config.dev.cacheBusting,

//编译时将“引入路径”转换为require调用,使其可由webpack处理

transformToRequire: {

video: ['src', 'poster'],

source: 'src',

img: 'src',

image: 'xlink:href'

}

}

(5)webpack.base.conf.js:开发、测试、生产环境的公共基础配置文件,配置输出环境,配置模块resolve和插件等

'use strict'

const path = require('path')// node自带的文件路径工具

const utils = require('./utils')// 工具函数集合

const config = require('../config')// 配置文件

const vueLoaderConfig = require('./vue-loader.conf')// 工具函数集合

/**

* 获取"绝对路径"

* @method resolve

* @param {String} dir 相对于本文件的路径

* @return {String} 绝对路径

*/

function resolve(dir) {

return path.join(__dirname, '..', dir)

}

module.exports = {

context: path.resolve(__dirname, '../'),

//入口js文件(默认为单页面所以只有app一个入口)

entry: {

app: './src/main.js'

},

//配置出口

output: {

path: config.build.assetsRoot,//打包编译的根路径(dist)

filename: '[name].js',

publicPath: process.env.NODE_ENV === 'production'

? config.build.assetsPublicPath

: config.dev.assetsPublicPath//发布路径

},

resolve: {

extensions: ['.js', '.vue', '.json'],// 自动补全的扩展名

//别名配置

alias: {

'vue$': 'vue/dist/vue.esm.js',

'@': resolve('src'),// eg:"src/components" => "@/components"

}

},

module: {

rules: [

//使用vue-loader将vue文件编译转换为js

{

test: /.vue$/,

loader: 'vue-loader',

options: vueLoaderConfig

},

//通过babel-loader将ES6编译压缩成ES5

{

test: /.js$/,

loader: 'babel-loader',

include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]

},

//使用url-loader处理(图片、音像、字体),超过10000编译成

{

test: /.(png|jpe?g|gif|svg)(?.*)?$/,

loader: 'url-loader',

options: {

limit: 10000,

name: utils.assetsPath('img/[name].[hash:7].[ext]')

}

},

{

test: /.(mp4|webm|ogg|mp3|wav|flac|aac)(?.*)?$/,

loader: 'url-loader',

options: {

limit: 10000,

name: utils.assetsPath('media/[name].[hash:7].[ext]')

}

},

{

test: /.(woff2?|eot|ttf|otf)(?.*)?$/,

loader: 'url-loader',

options: {

limit: 10000,

name: utils.assetsPath('fonts/[name].[hash:7].[ext]')

}

}

]

},

//nodeJs全局变量/模块,防止webpack注入一些nodeJs的东西到vue中

node: {

setImmediate: false,

dgram: 'empty',

fs: 'empty',

net: 'empty',

tls: 'empty',

child_process: 'empty'

}

}

(6)webpack.dev.conf.js:webpack配置开发环境中的入口

'use strict'

const utils = require('./utils')

const webpack = require('webpack')

const config = require('../config')

const merge = require('webpack-merge')//webpack-merge实现合并

const path = require('path')

const baseWebpackConfig = require('./webpack.base.conf')

const CopyWebpackPlugin = require('copy-webpack-plugin')

const HtmlWebpackPlugin = require('html-webpack-plugin')

const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')//webpack的提示错误和日志信息的插件

const portfinder = require('portfinder')// 查看空闲端口位置,默认情况下搜索8000这个端口

const HOST = process.env.HOST

const PORT = process.env.PORT && Number(process.env.PORT)

const devWebpackConfig = merge(baseWebpackConfig, {

module: {

rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })

},

devtool: config.dev.devtool,//调试模式

devServer: {

clientLogLevel: 'warning',

historyApiFallback: {//使用 HTML5 History API 时, 404 响应替代为 index.html

rewrites: [

{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },

],

},

hot: true,//热重载

contentBase: false, // 提供静态文件访问

compress: true,//压缩

host: HOST || config.dev.host,

port: PORT || config.dev.port,

open: config.dev.autoOpenBrowser,//npm run dev 时自动打开浏览器

overlay: config.dev.errorOverlay

? { warnings: false, errors: true }

: false,// 显示warning 和 error 信息

publicPath: config.dev.assetsPublicPath,

proxy: config.dev.proxyTable,//api代理

quiet: true, //控制台打印警告和错误(用FriendlyErrorsPlugin 为 true)

watchOptions: {// 检测文件改动

poll: config.dev.poll,

}

},

plugins: [

new webpack.DefinePlugin({

'process.env': require('../config/dev.env')

}),

new webpack.HotModuleReplacementPlugin(),//模块热替换插件,修改模块时不需要刷新页面

new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.

new webpack.NoEmitsPlugin(),//webpack编译错误的时候,中断打包进程,防止错误代码打包到文件中

// 将打包编译好的代码插入index.html

new HtmlWebpackPlugin({

filename: 'index.html',

template: 'index.html',

inject: true

}),

// 提取static assets 中css 复制到dist/static文件

new CopyWebpackPlugin([

{

from: path.resolve(__dirname, '../static'),

to: config.dev.assetsSubDirectory,

ignore: ['.*']//忽略.*的文件

}

])

]

})

module.exports = new Promise((resolve, reject) => {

portfinder.basePort = process.env.PORT || config.dev.port

portfinder.getPort((err, port) => { //查找端口号

if (err) {

reject(err)

} else {

//端口被占用时就重新设置evn和devServer的端口

process.env.PORT = port

devWebpackConfig.devServer.port = port

// npm run dev成功的友情提示

devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({

compilationSuccessInfo: {

messages: [`Your application is running here: ],

},

s: config.dev.notifys

? utils.createNotifierCallback()

: undefined

}))

resolve(devWebpackConfig)

}

})

})

(7)webpack.dev.prod.js:webpack配置生产环境中的入口

'use strict'

const path = require('path')

const utils = require('./utils')

const webpack = require('webpack')

const config = require('../config')

const merge = require('webpack-merge')

const baseWebpackConfig = require('./webpack.base.conf')

const CopyWebpackPlugin = require('copy-webpack-plugin')

const HtmlWebpackPlugin = require('html-webpack-plugin')

const ExtractTextPlugin = require('extract-text-webpack-plugin')

const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

const env = require('../config/prod.env')

const webpackConfig = merge(baseWebpackConfig, {

module: {

rules: utils.styleLoaders({

sourceMap: config.build.productionSourceMap,

extract: true,

usePostCSS: true

})

},

devtool: config.build.productionSourceMap ? config.build.devtool : false,//是否开启调试模式

output: {

path: config.build.assetsRoot,

filename: utils.assetsPath('js/[name].[chunkhash].js'),

chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')

},

plugins: [

new webpack.DefinePlugin({

'process.env': env

}),

new UglifyJsPlugin({//压缩js

uglifyOptions: {

compress: {

warnings: false

}

},

sourceMap: config.build.productionSourceMap,

parallel: true

}),

new ExtractTextPlugin({//提取静态文件,减少请求

filename: utils.assetsPath('css/[name].[contenthash].css'),

allChunks: true,

}),

new OptimizeCSSPlugin({//提取优化压缩后(删除来自不同组件的冗余代码)的css

cssProcessorOptions: config.build.productionSourceMap

? { safe: true, map: { inline: false } }

: { safe: true }

}),

new HtmlWebpackPlugin({ //html打包压缩到index.html

filename: config.build.index,

template: 'index.html',

inject: true,

minify: {

removeComments: true,//删除注释

collapseWhitespace: true,//删除空格

removeAttributeQuotes: true//删除属性的引号

},

chunksSortMode: 'dependency'//模块排序,按照我们需要的顺序排序

}),

new webpack.HashedModuleIdsPlugin(),

new webpack.optimize.ModuleConcatenationPlugin(),

new webpack.optimize.CommonsChunkPlugin({ // node_modules中的任何所需模块都提取到vendor

name: 'vendor',

minChunks (module) {

return (

module.resource &&

/.js$/.test(module.resource) &&

module.resource.indexOf(

path.join(__dirname, '../node_modules')

) === 0

)

}

}),

new webpack.optimize.CommonsChunkPlugin({

name: 'manifest',

minChunks: Infinity

}),

new webpack.optimize.CommonsChunkPlugin({

name: 'app',

async: 'vendor-async',

children: true,

minChunks: 3

}),

new CopyWebpackPlugin([//复制static中的静态资源(默认到dist里面)

{

from: path.resolve(__dirname, '../static'),

to: config.build.assetsSubDirectory,

ignore: ['.*']

}

])

]

})

if (config.build.productionGzip) {

const CompressionWebpackPlugin = require('compression-webpack-plugin')

webpackConfig.plugins.push(

new CompressionWebpackPlugin({

asset: '[path].gz[query]',

algorithm: 'gzip',

test: new RegExp(

'\.('

config.build.productionGzipExtensions.join('|')

')$'

),

threshold: 10240,

minRatio: 0.8

})

)

}

if (config.build.bundleAnalyzerReport) {

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

webpackConfig.plugins.push(new BundleAnalyzerPlugin())

}

module.exports = webpackConfig

2、config文件夹:

config文件夹的结构:

澳门新萄京官方网站 10

(1) dev.env.js和prod.env.js:分别配置:开发环境和生产环境。这个可以根据公司业务结合后端需求配置需要区分开发环境和测试环境的属性

'use strict'

const merge = require('webpack-merge')

const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {

NODE_ENV: '"development"'

})

ps:webpack-merge用于实现合并类似于ES6的Object.assign()

'use strict'

module.exports = {

NODE_ENV: '"production"'

}

(*注意属性值要用“‘’”双层引住),访问(获取值)时直接用:

process.env.属性名

ps:process(进程)是nodejs的一个全局变量,process.env 属性返回一个用户环境信息的对象

(2)index.js配置解析:

'use strict';

const path = require('path');

module.exports = {

// ===================开发环境配置

dev: {

assetsSubDirectory: 'static',//静态资源文件夹(一般存放css、js、image等文件)

assetsPublicPath: '/',//根目录

proxyTable: {},//配置API代理,可利用该属性解决跨域的问题

host: 'localhost', // 可以被 process.env.HOST 覆盖

port: 3030, // 可以被 process.env.PORT 覆盖

autoOpenBrowser: true,//编译后自动打开浏览器页面 host",默认"false"),设置路由重定向自动打开您的默认页面

errorOverlay: true,//浏览器错误提示

notifys: true,//跨平台错误提示

poll: false, //webpack提供的使用文件系统(file system)获取文件改动的通知devServer.watchOptions(监控文件改动)

devtool: 'cheap-module-eval-source-map',//webpack提供的用来调试的模式,有多个不同值代表不同的调试模式

cacheBusting: true,// 配合devtool的配置,当给文件名插入新的hash导致清除缓存时是否生成source-map

cssSourceMap: true //记录代码压缩前的位置信息,当产生错误时直接定位到未压缩前的位置,方便调试

},

// ========================生产环境配置

build: {

index: path.resolve(__dirname, '../dist/index.html'),//编译后"首页面"生成的绝对路径和名字

assetsRoot: path.resolve(__dirname, '../dist'),//打包编译的根路径(默认dist,存放打包压缩后的代码)

assetsSubDirectory: 'static',//静态资源文件夹(一般存放css、js、image等文件)

assetsPublicPath: '/',//发布的根目录(dist文件夹所在路径)

productionSourceMap: true,//是否开启source-map

devtool: '#source-map',//(详细参见:)

productionGzip: false,//是否压缩

productionGzipExtensions: ['js', 'css'],//unit的gzip命令用来压缩文件(gzip模式下需要压缩的文件的扩展名有js和css)

bundleAnalyzerReport: process.env.npm_config_report //是否开启打包后的分析报告

}

};

3、node_modules文件夹:存放npm install时根据package.json配置生成的npm安装包的文件夹

4、src文件夹:我们需要在src文件夹中开发代码,打包时webpack会根据build中的规则(build规则依赖于config中的配置)将src打包压缩到dist文件夹在浏览器中运行

(1)assets文件:用于存放静态资源(css、image),assets打包时路径会经过webpack中的file-loader编译(因此,assets需要使用绝对路径)成js

(2)components文件夹:用来存放 .vue 组件(实现复用等功能,如:过滤器,列表项等)

(3)router文件夹:在router/index.js文件中配置页面路由

(4)App.vue:是整个项目的主组件,所有页面都是通过使用<router-view/>开放入口在App.vue下进行切换的(所有的路由都是App.vue的子组件)

(5)main.js:入口js文件(全局js,你可以在这里:初始化vue实例、require/import需要的插件、注入router路由、引入store状态管理)

5、static文件夹:webpack默认存放静态文件(css、image)的文件夹,与assets不同的是:static在打包时会直接复制一个同名文件夹到dist文件夹里(不会经过编译,可使用相对路径)

6、其他文件:

(1).babelrc:浏览器解析的兼容配置,该文件主要是对预设(presets)和插件(plugins)进行配置,因此不同的转译器作用不同的配置项,大致可分为:语法转义器、补丁转义器、sx和flow插件

(2).editorconfig:用于配置代码格式(配合代码检查工具使用,如:ESLint,团队开发时可统一代码风格),这里配置的代码规范规则优先级高于编辑器默认的代码格式化规则 。

(3).gitignore:配置git提交时需要忽略的文件

(4)postcssrc.js: autoprefixer(自动补全css样式的浏览器前缀);postcss-import(@import引入语法)、CSS Modules(规定样式作用域)

(5)index.html:项目入口页面,编译之后所有代码将插入到这来

(6)package.json:npm的配置文件(npm install根据package.json下载对应版本的安装包)

(7)package.lock.json:npm install(安装)时锁定各包的版本号

(8)README.md:项目使用说明

2、安装一个好用的命令行工具

在windows环境下,系统默认的cmd非常难用,所以我个人比较推荐大家使用git.bash 或者 cmder。

git 下载地址:
在git安装目录下会有一个bash工具,找到安装目录直接使用即可。

cmder下载地址:

在mac上就方便很多了,你可以直接使用系统自带的terminal工具,就非常好用。但是一般我推荐大家使用iterm2,并安装oh my zsh插件。具体的配置大家可以自己去折腾,网上的教程应该足够帮助你搞定这一切了。

  • iterm2 下载地址
  • oh my zsh 主题选择

澳门新萄京官方网站 11

另外还强烈推荐一款超高颜值的终端工具 hyperTerm

这款工具的特色就是颜值高,第一感觉就是惊艳,大家不妨一试。

澳门新萄京官方网站 12

  • hyperTerm 下载地址

二、不使用脚手架手动安装 React 项目

    安装项目依赖包

1、安装node.js  将镜像改成淘宝的 使用cnpm进行安装

2、打开cmd(小黑窗)进入到项目目录

澳门新萄京官方网站 13

自己手动创建项目目录并切换到目录下

3、安装包管理 执行命令  cnpm init 直接回车,直接使用默认值即可,也可以根据提示自己自定义项目内容

澳门新萄京官方网站 14

配置 package.json 的基本信息

按照以下顺序进行安装相关依赖  (其中 -D 同 --save 一样,都是将安装的包名称和版本号记录在 pachage.json 中)

cnpm install react -D                             #react本身

cnpm install react-dom -D                     #react-dom本身

cnpm install react-hot-loader -D            #react热更新

#babel相关的库

cnpm install babel-core -D                      #后台编译

cnpm install babelify -D                          #

cnpm install babel-preset-react -D         #bable-react预设

cnpm install babel-preset-es2015 -D      #babel对ES2015的预设

cnpm install babel-loader -D                    #babel加载器

澳门新萄京官方网站 15

安装 react 及 react-dom

澳门新萄京官方网站 16

安装 babel-core 

澳门新萄京官方网站 17

安装 babelify 、babel-preset-react 、babel-preset-es2015

安装完成后在项目文件夹下的 package.json 中就可以查看已经安装的包文件

澳门新萄京官方网站 18

查看已安装项目

使用webpack进行打包,进行webpack包依赖安装

#首先先安装全局 webpack

cnpm install -g webpack                         #webpack的本地依赖库  -g  是指全局安装

cnpm install -g webpack-dev-server       #webpack服务器的本地依赖库

安装新版本的webpack 会造成一直提示让安装 webpack-cli 的提示,所以尽可能先安装 老版本 webpack1.13.2版本 

webpack 安装1.13.2 版本,安装之前卸载之前的webpack ,全局和文件夹内都卸载一遍

npm uninstall webpack -g   (全局卸载)

npm uninstall webpack    (从项目文件夹中卸载)

全局安装指定版本包                       cnpm install -g webpack@1.13.2

在项目文件夹中安装指定版本包   cnpm install webpack@1.13.2 -D

澳门新萄京官方网站 19

webpack 全局安装如图

澳门新萄京官方网站 20

 webpack-dev-server全局安装如图

#其次再安装webpack到项目中

cnpm install webpack -D                        #webpack的本地依赖库  -g  是指全局安装

cnpm install webpack-dev-server -D      #webpack服务器的本地依赖库

澳门新萄京官方网站 21

安装如图

如果出现红色警告则不用去管,没问题。此时查看  package.json则会发现webpack的包已经安装上了

澳门新萄京官方网站 22

查看安装结果

在根目录配置webpack配置文件  webpack.config.js (文件名称是固定的,不需要改变)  如果设置其他名称则系统不能自动找到,需要在配置文件中进行指定

webpack版本为3.8.1 ,其配置文件内容如下:

澳门新萄京官方网站 23

webpack.config.js 配置

澳门新萄京官方网站 24

项目文件夹布局

index.html 及 indes.js 文件内容

澳门新萄京官方网站 25

index.html 及 indes.js 文件内容

澳门新萄京官方网站 26

webpack.config.js 文件

然后进入到项目目录下在cmd中执行命令:webpack  进行打包,如果有错误会直接报错

澳门新萄京官方网站 27

使用 webpack  进行编译打包

如果 出现以下界面则是编译成功

澳门新萄京官方网站 28

编译打包成功

原项目中要将引入的index.js 替换成编译之后的bundle.js 文件,然后执行webpack命令则编译成功之后的文件就生效,在浏览器中可看到结果

在没有执行自动化监测之前,每次改变文件内容都需要执行一次命令重新编译一次文件,这样浏览器页面才会改变起作用

因为安装了webpack-dev-server 服务,所以可以使用自动化监测,执行命令 webpack --watch   则可运行,结束按ctrl c 

这样每次改变文件之后,服务则会自动执行一次编译,每次编译的hash值都是不同的

澳门新萄京官方网站 29

但是这样子每次都需要刷新浏览器,执行如下:webpack-dev-server 命令使用该命令所给的链接则可以访问项目并在项目改变的情况下无需手动刷新浏览器则会自动刷新内容(实验失败,未成功)小伙伴们可以自行测试,一般建议用脚手架安装比较方便,每次更新都会自动刷新

webpack的使用说明文档    

澳门新萄京官方网站 30

2. 对外提供接口

ES6 modules使用export关键字对外提供接口,在我们刚才创建的test.js中,我们添加如下代码

   const num = 20;
    const arr = [1, 2, 3, 4];
    const obj = {
        a: 0,
        b: function() {}
    }
    const foo = () => {
        const a = 0;
        const b = 20;
        return a   b;
    }

    export default {
        num,
        arr,
        obj,
        foo
    }

 

在test.js中,我们使用export default对包暴露了一个对象。他的意思就是当我们使用import test from ‘./test’时,这个test对象就默认等于export default暴露的对象。

我们还可以在test.js中,仅仅通过export暴露几个方法与属性,我们来看看index.js中test会变成什么样子。

// src/test.js
export const bar = () => {}
export const zcar = 12345;

 

保存运行后,我们发现,index.js中的test对象并没有变化,因为它仅仅等于export default抛出的对象,因此,为了获得模块test.js暴露的所有接口,我们得通过如下的方式。

// src/index.js
import * as test from './test';

 

其中的 表示所有,这是比较常用的通配符,as表示别名, as test的意思是将test.js暴露的所有接口组成的对象,命名为test。那么我们在index.js中log出test,结果就如下。

 

澳门新萄京官方网站 31

 

如果大家对ES6解析结构的语法熟悉,那么对于如下的用法相信就不难理解。

/ src/index.js
import test, { bar, zcar } from './test';

console.log(test);
console.log('bar:', bar);
console.log('zcar:', zcar);

 

test,仍然表示为export default暴露的对象,而 { bar, zcar }则表示利用解析结构的语法,从整个返回对象中去取得对应的接口。输出结果也就很清晰了。

 

澳门新萄京官方网站 32

 

这种方式还是比较常见,比如我们在使用vuex时,常常这样使用:

import { mapMutations } from "Vuex";

 

它其实暗示了vuex的封装方式,也暗示了我们应该如何去封装我们的模块。

这里我们能够直接引入vuex的原因,是因为我们将它安装到了文件夹node_modules中,该文件夹中安装的所有模块都可以这样直接引用。例如我们安装一个jquery。

// 安装jquery
> npm install jquery

然后在其他模块中就可以直接引入

import $ from 'jquery'

 

这样,我们可以和往常一样使用jquery。
通过这样方式,我们还可以扩展更多的库,这就使得我们这个开发环境不仅仅能够用于vue的开发,怎么用,完全取决与你自己。

五、运行项目

在webStorm中打开项目,首先赶紧右击Project进行如下操作(否则会卡死,还有各种其他方法参见:

澳门新萄京官方网站 33

(1)启动安装:cnpm install

澳门新萄京官方网站 34

(2)然后npm run dev:跑起来~

澳门新萄京官方网站 35

(3)生成打包文件 :npm run build

然后你会发现项目多了个dist文件夹(用于部署到生产环境用,是打包压缩之后的src文件夹)

澳门新萄京官方网站 36

© 著作权归作者所有返回搜狐,查看更多

责任编辑:

3、安装create-react-app

在命令行工具中使用查看版本的方式确保node与npm都安装好之后,我们就可以安装create-react-app了。

> node -v // 输出node版本号 > npm -v // 输出npm版本号

1
2
3
4
5
> node -v
// 输出node版本号
 
> npm -v
// 输出npm版本号

使用npm全局安装create-react-app

> npm install create-react-app -g

1
> npm install create-react-app -g

然后我们就可以使用create-react-app来创建我们的第一个项目。

找到一个你要存放项目的根目录,假设叫做develop,运行以下指令。

> create-react-app es6app

1
> create-react-app es6app

create-react-app会自动帮助我们在develop目录下创建一个叫做es6app的文件夹,这就是我们新创建的项目。

当项目创建完成之后,在命令行工具中,我们会看到如图所示的提示。这些提示告诉了我们如何运行项目npm start ,如何打包项目npm run build等,这里我就不再赘述。

澳门新萄京官方网站 37

项目创建完毕之后,进入该文件夹。

> cd es6app // 查看文件夹里的内容 > ls

1
2
3
4
> cd es6app
 
// 查看文件夹里的内容
> ls

我们会发现里面有一个叫做package.json的文件,这个文件里包含了项目所需要的所有依赖。当我们第一次运行项目之前,还需要安装该文件里的依赖包。

> npm install

1
> npm install

安装完毕之后,我们就可以启动该项目了。

> npm start

1
> npm start

澳门新萄京官方网站 38

项目启动之后

一般来说,启动之后会自动在浏览器中打开。

澳门新萄京官方网站 39

项目首次启动的页面

create-react-app已经自动帮助我们实现了热更新,因此当我们修改代码时,浏览器会自动更新。当然,如果我们仅仅只是修改页面样式时,热更新将会非常方便,但是如果你正在进行单页面的组件开发,可能热更新能够提供的帮助非常有限。

结束语

ES6 模块的基础语法大概就这些吧,他告诉了我们在ES6中,一个模块应该如何对外暴露接口与如何引入其他模块暴露的接口,这个知识点在实际开发中非常常用,因此虽然简单,但是不得不掌握,这也是大家进一步学习react或者vue的基础,主要的难点大概在于本地开发环境的折腾,如果你是初次折腾这些,可能会遇到一些小问题,所以一定要有一点耐心。

4、认识项目

只要我们按照构建工具的规则进行开发,那么构建工具会自动帮助我们将代码进行整合,因此在该项目中开发时,我们并不需要自己来使用script或者link标签来引入js与css,所以认识create-react-app的规则就变得很重要。

初次创建的项目下,会有3个文件夹。

  • node_modules
    项目依赖包存放位置。当我们运行npm install安装package.json中的依赖包时,该文件夹会自动创建,所有的依赖包会安装到该文件夹里。
  • public
    主要的作用是html入口文件的存放。当然我们也可以存放其他公用的静态资源,如图片,css等。其中的index.html就是我们项目的入口html文件
  • src
    组件的存放目录。在create-react-app创建的项目中,每一个单独的文件都可以被看成一个单独的模块,单独的image,单独的css,单独js等,而所有的组件都存放于src目录中,其中index.js则是js的入口文件。虽然我们并没有在index.html中使用script标签引入他,但是他的作用就和此一样。

当然,如果我们要进一步进行react的学习,那么肯定需要了解多一点的规则,但是在学习react之前,我们还是先把ES6 modules的知识搞定在说吧,所以,接下来你要做的事情就是,删掉src目录里的除了index.js之外的所有文件,并清空index.js,我们从0开始学习ES6 modules。

为了确保程序仍然能够正常运行,我们在index.js中随便写点代码测试一下

const app = document.querySelector('#root') app.innerHTML = '啊,全部被清空啦,准备工作终于做完了,可以开始学习ES6啦'

1
2
const app = document.querySelector('#root')
app.innerHTML = '啊,全部被清空啦,准备工作终于做完了,可以开始学习ES6啦'

澳门新萄京官方网站 40

一切正常,程序变得普通了,我们更容易理解

那么我们就可以在这个环境下学习ES6的所有知识了,当然也包括ES6 modules。

ES6 modules

1. 引入模块

首先在src目录下创建一个test.js,在test.js中我们随便干点什么简单的事情即可。

// src/test.js console.log('your first module');

1
2
// src/test.js
console.log('your first module');

在index.js中通过import引入test.js,这是我们要学会的第一个语法

// src/index.js import test from './test' console.log(test);

1
2
3
4
// src/index.js
import test from './test'
 
console.log(test);
  • import表示引入一个模块,
  • test 我们暂时理解为引入模块的名字,
  • from表示从哪里引入
  • ./test./test.js的简写,表示将要引入模块的路径

澳门新萄京官方网站 41

结果是test中的代码执行,index.js中模块test为一个空对象

引入这个动作执行时,test.js中的代码也执行了。由于在test.js中并没有对外暴露任何接口,因此index.js中的test为一个空对象,那么对外暴露接口的方式,则是我们要学习的第二个语法。

2. 对外提供接口

ES6 modules使用export关键字对外提供接口,在我们刚才创建的test.js中,我们添加如下代码

// test.js const num = 20; const arr = [1, 2, 3, 4]; const obj = { a: 0, b: function() {} } const foo = () => { const a = 0; const b = 20; return a b; } export default { num, arr, obj, foo }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// test.js
const num = 20;
const arr = [1, 2, 3, 4];
const obj = {
    a: 0,
    b: function() {}
}
const foo = () => {
    const a = 0;
    const b = 20;
    return a b;
}
 
export default {
    num,
    arr,
    obj,
    foo
}

澳门新萄京官方网站 42

运行结果

test.js中,我们使用export default对包暴露了一个对象。他的意思就是当我们使用import test from './test'时,这个test对象就默认等于export default暴露的对象。

我们还可以在test.js中,仅仅通过export暴露几个方法与属性,我们来看看index.js中test会变成什么样子。

// src/test.js export const bar = () => {} export const zcar = 12345;

1
2
3
// src/test.js
export const bar = () => {}
export const zcar = 12345;

保存运行后,我们发现,index.js中的test对象并没有变化,因为它仅仅等于export default抛出的对象,因此,为了获得模块test.js暴露的所有接口,我们得通过如下的方式。

// src/index.js import * as test from './test';

1
2
// src/index.js
import * as test from './test';

其中的 * 表示所有,这是比较常用的通配符,as表示别名,* as test的意思是将test.js暴露的所有接口组成的对象,命名为test。那么我们在index.js中log出test,结果就如下。

澳门新萄京官方网站 43

看到结果,我们就很容易清楚的知道export与export default的区别与作用了,并且如何使用他们就变得很简单了

如果大家还记得前面一篇文章里,我所讲的ES6解析结构的语法,那么对于如下的用法相信就不难理解。

// src/index.js import test, { bar, zcar } from './test'; console.log(test); console.log('bar:', bar); console.log('zcar:', zcar);

1
2
3
4
5
6
// src/index.js
import test, { bar, zcar } from './test';
 
console.log(test);
console.log('bar:', bar);
console.log('zcar:', zcar);

test,仍然表示为export default暴露的对象,而 { bar, zcar }则表示利用解析结构的语法,从整个返回对象中去取得对应的接口。输出结果也就很清晰了。

澳门新萄京官方网站 44

result

这种方式还是比较常见,比如我们在使用react时,常常这样使用:

import React, { Component } from 'react'

1
import React, { Component } from 'react'

它其实暗示了React的封装方式,也暗示了我们应该如何去封装我们的模块。

这里我们能够直接引入react的原因,是因为我们将它安装到了文件夹node_modules中,该文件夹中安装的所有模块都可以这样直接引用。例如我们安装一个jquery。

// 安装jquery > npm install jquery

1
2
// 安装jquery
> npm install jquery

然后在其他模块中就可以直接引入

import $ from 'jquery'

1
import $ from 'jquery'

这样,我们可以和往常一样使用jquery。
通过这样方式,我们还可以扩展更多的库,这就使得我们这个开发环境不仅仅能够用于react的开发,怎么用,完全取决与你自己。

OK,ES6 模块的基础语法大概就这些吧,他告诉了我们在ES6中,一个模块应该如何对外暴露接口与如何引入其他模块暴露的接口,这个知识点在实际开发中非常常用,因此虽然简单,但是不得不掌握,这也是大家进一步学习react或者vue的基础,主要的难点大概在于本地开发环境的折腾,如果你是初次折腾这些,可能会遇到一些小问题,所以一定要有一点耐心。

通常来说,一个知识点,在完全理解之前还是有点难度的,但是理解之后就变得非常简单,所以如果你在学习这个知识点时感觉有点困难,也不要过于担心,多多动手尝试,并在实践中运用起来,相信很快就能掌握。

1 赞 2 收藏 评论

澳门新萄京官方网站 45

本文由澳门新萄京官方网站发布于澳门新萄京赌场网址,转载请注明出处:澳门新萄京官方网站:webpack搭建vue最全分析,实

关键词: