webpack进阶,前端开发网页

}

]

},

/* config.module.rule(‘media’) */

{

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

use: [

/* config.module.rule(‘media’).use(‘url-loader’) */

{

loader: ‘//node_modules/url-loader/dist/cjs.js’,

options: {

limit: 4096,

fallback: {

loader: ‘//node_modules/file-loader/dist/cjs.js’,

options: {

name: ‘media/[name].[hash:8].[ext]’

}

}

}

}

]

},

/* config.module.rule(‘fonts’) */

{

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

use: [

/* config.module.rule(‘fonts’).use(‘url-loader’) */

{

loader: ‘//node_modules/url-loader/dist/cjs.js’,

options: {

limit: 4096,

fallback: {

loader: ‘//node_modules/file-loader/dist/cjs.js’,

options: {

name: ‘fonts/[name].[hash:8].[ext]’

}

}

}

}

]

},

/* config.module.rule(‘pug’) */

{

test: /.pug$/,

oneOf: [

/* config.module.rule(‘pug’).oneOf(‘pug-vue’) */

{

resourceQuery: /vue/,

use: [

/* config.module.rule(‘pug’).oneOf(‘pug-vue’).use(‘pug-plain-loader’) */

{

loader: ‘pug-plain-loader’

}

]

},

/* config.module.rule(‘pug’).oneOf(‘pug-template’) */

{

use: [

/* config.module.rule(‘pug’).oneOf(‘pug-template’).use(‘raw’) */

{

loader: ‘raw-loader’

},

/* config.module.rule(‘pug’).oneOf(‘pug-template’).use(‘pug-plain-loader’) */

{

loader: ‘pug-plain-loader’

}

]

}

]

},

/* config.module.rule(‘css’) */

{

test: /.css$/,

oneOf: [

/* config.module.rule(‘css’).oneOf(‘vue-modules’) */

{

resourceQuery: /module/,

use: [

/* config.module.rule(‘css’).oneOf(‘vue-modules’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘css’).oneOf(‘vue-modules’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2,

modules: {

localIdentName: ‘[name][local][hash:base64:5]’

}

}

},

/* config.module.rule(‘css’).oneOf(‘vue-modules’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

}

]

},

/* config.module.rule(‘css’).oneOf(‘vue’) */

{

resourceQuery: /?vue/,

use: [

/* config.module.rule(‘css’).oneOf(‘vue’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘css’).oneOf(‘vue’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2

}

},

/* config.module.rule(‘css’).oneOf(‘vue’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

}

]

},

/* config.module.rule(‘css’).oneOf(‘normal-modules’) */

{

test: /.module.\w+$/,

use: [

/* config.module.rule(‘css’).oneOf(‘normal-modules’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘css’).oneOf(‘normal-modules’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2,

modules: {

localIdentName: ‘[name][local][hash:base64:5]’

}

}

},

/* config.module.rule(‘css’).oneOf(‘normal-modules’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

}

]

},

/* config.module.rule(‘css’).oneOf(‘normal’) */

{

use: [

/* config.module.rule(‘css’).oneOf(‘normal’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘css’).oneOf(‘normal’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2

}

},

/* config.module.rule(‘css’).oneOf(‘normal’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

}

]

}

]

},

/* config.module.rule(‘postcss’) */

{

test: /.p(ost)?css$/,

oneOf: [

/* config.module.rule(‘postcss’).oneOf(‘vue-modules’) */

{

resourceQuery: /module/,

use: [

/* config.module.rule(‘postcss’).oneOf(‘vue-modules’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘postcss’).oneOf(‘vue-modules’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2,

modules: {

localIdentName: ‘[name][local][hash:base64:5]’

}

}

},

/* config.module.rule(‘postcss’).oneOf(‘vue-modules’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

}

]

},

/* config.module.rule(‘postcss’).oneOf(‘vue’) */

{

resourceQuery: /?vue/,

use: [

/* config.module.rule(‘postcss’).oneOf(‘vue’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘postcss’).oneOf(‘vue’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2

}

},

/* config.module.rule(‘postcss’).oneOf(‘vue’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

}

]

},

/* config.module.rule(‘postcss’).oneOf(‘normal-modules’) */

{

test: /.module.\w+$/,

use: [

/* config.module.rule(‘postcss’).oneOf(‘normal-modules’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘postcss’).oneOf(‘normal-modules’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2,

modules: {

localIdentName: ‘[name][local][hash:base64:5]’

}

}

},

/* config.module.rule(‘postcss’).oneOf(‘normal-modules’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

}

]

},

/* config.module.rule(‘postcss’).oneOf(‘normal’) */

{

use: [

/* config.module.rule(‘postcss’).oneOf(‘normal’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘postcss’).oneOf(‘normal’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2

}

},

/* config.module.rule(‘postcss’).oneOf(‘normal’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

}

]

}

]

},

/* config.module.rule(‘scss’) */

{

test: /.scss$/,

oneOf: [

/* config.module.rule(‘scss’).oneOf(‘vue-modules’) */

{

resourceQuery: /module/,

use: [

/* config.module.rule(‘scss’).oneOf(‘vue-modules’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘scss’).oneOf(‘vue-modules’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2,

modules: {

localIdentName: ‘[name][local][hash:base64:5]’

}

}

},

/* config.module.rule(‘scss’).oneOf(‘vue-modules’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘scss’).oneOf(‘vue-modules’).use(‘sass-loader’) */

{

loader: ‘sass-loader’,

options: {

sourceMap: false

}

}

]

},

/* config.module.rule(‘scss’).oneOf(‘vue’) */

{

resourceQuery: /?vue/,

use: [

/* config.module.rule(‘scss’).oneOf(‘vue’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘scss’).oneOf(‘vue’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2

}

},

/* config.module.rule(‘scss’).oneOf(‘vue’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘scss’).oneOf(‘vue’).use(‘sass-loader’) */

{

loader: ‘sass-loader’,

options: {

sourceMap: false

}

}

]

},

/* config.module.rule(‘scss’).oneOf(‘normal-modules’) */

{

test: /.module.\w+$/,

use: [

/* config.module.rule(‘scss’).oneOf(‘normal-modules’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘scss’).oneOf(‘normal-modules’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2,

modules: {

localIdentName: ‘[name][local][hash:base64:5]’

}

}

},

/* config.module.rule(‘scss’).oneOf(‘normal-modules’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘scss’).oneOf(‘normal-modules’).use(‘sass-loader’) */

{

loader: ‘sass-loader’,

options: {

sourceMap: false

}

}

]

},

/* config.module.rule(‘scss’).oneOf(‘normal’) */

{

use: [

/* config.module.rule(‘scss’).oneOf(‘normal’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘scss’).oneOf(‘normal’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2

}

},

/* config.module.rule(‘scss’).oneOf(‘normal’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘scss’).oneOf(‘normal’).use(‘sass-loader’) */

{

loader: ‘sass-loader’,

options: {

sourceMap: false

}

}

]

}

]

},

/* config.module.rule(‘sass’) */

{

test: /.sass$/,

oneOf: [

/* config.module.rule(‘sass’).oneOf(‘vue-modules’) */

{

resourceQuery: /module/,

use: [

/* config.module.rule(‘sass’).oneOf(‘vue-modules’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘sass’).oneOf(‘vue-modules’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2,

modules: {

localIdentName: ‘[name][local][hash:base64:5]’

}

}

},

/* config.module.rule(‘sass’).oneOf(‘vue-modules’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘sass’).oneOf(‘vue-modules’).use(‘sass-loader’) */

{

loader: ‘sass-loader’,

options: {

sourceMap: false,

sassOptions: {

indentedSyntax: true

}

}

}

]

},

/* config.module.rule(‘sass’).oneOf(‘vue’) */

{

resourceQuery: /?vue/,

use: [

/* config.module.rule(‘sass’).oneOf(‘vue’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘sass’).oneOf(‘vue’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2

}

},

/* config.module.rule(‘sass’).oneOf(‘vue’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘sass’).oneOf(‘vue’).use(‘sass-loader’) */

{

loader: ‘sass-loader’,

options: {

sourceMap: false,

sassOptions: {

indentedSyntax: true

}

}

}

]

},

/* config.module.rule(‘sass’).oneOf(‘normal-modules’) */

{

test: /.module.\w+$/,

use: [

/* config.module.rule(‘sass’).oneOf(‘normal-modules’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘sass’).oneOf(‘normal-modules’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2,

modules: {

localIdentName: ‘[name][local][hash:base64:5]’

}

}

},

/* config.module.rule(‘sass’).oneOf(‘normal-modules’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘sass’).oneOf(‘normal-modules’).use(‘sass-loader’) */

{

loader: ‘sass-loader’,

options: {

sourceMap: false,

sassOptions: {

indentedSyntax: true

}

}

}

]

},

/* config.module.rule(‘sass’).oneOf(‘normal’) */

{

use: [

/* config.module.rule(‘sass’).oneOf(‘normal’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘sass’).oneOf(‘normal’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2

}

},

/* config.module.rule(‘sass’).oneOf(‘normal’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘sass’).oneOf(‘normal’).use(‘sass-loader’) */

{

loader: ‘sass-loader’,

options: {

sourceMap: false,

sassOptions: {

indentedSyntax: true

}

}

}

]

}

]

},

/* config.module.rule(‘less’) */

{

test: /.less$/,

oneOf: [

/* config.module.rule(‘less’).oneOf(‘vue-modules’) */

{

resourceQuery: /module/,

use: [

/* config.module.rule(‘less’).oneOf(‘vue-modules’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘less’).oneOf(‘vue-modules’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2,

modules: {

localIdentName: ‘[name][local][hash:base64:5]’

}

}

},

/* config.module.rule(‘less’).oneOf(‘vue-modules’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘less’).oneOf(‘vue-modules’).use(‘less-loader’) */

{

loader: ‘less-loader’,

options: {

sourceMap: false

}

}

]

},

/* config.module.rule(‘less’).oneOf(‘vue’) */

{

resourceQuery: /?vue/,

use: [

/* config.module.rule(‘less’).oneOf(‘vue’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘less’).oneOf(‘vue’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2

}

},

/* config.module.rule(‘less’).oneOf(‘vue’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘less’).oneOf(‘vue’).use(‘less-loader’) */

{

loader: ‘less-loader’,

options: {

sourceMap: false

}

}

]

},

/* config.module.rule(‘less’).oneOf(‘normal-modules’) */

{

test: /.module.\w+$/,

use: [

/* config.module.rule(‘less’).oneOf(‘normal-modules’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘less’).oneOf(‘normal-modules’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2,

modules: {

localIdentName: ‘[name][local][hash:base64:5]’

}

}

},

/* config.module.rule(‘less’).oneOf(‘normal-modules’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘less’).oneOf(‘normal-modules’).use(‘less-loader’) */

{

loader: ‘less-loader’,

options: {

sourceMap: false

}

}

]

},

/* config.module.rule(‘less’).oneOf(‘normal’) */

{

use: [

/* config.module.rule(‘less’).oneOf(‘normal’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘less’).oneOf(‘normal’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2

}

},

/* config.module.rule(‘less’).oneOf(‘normal’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘less’).oneOf(‘normal’).use(‘less-loader’) */

{

loader: ‘less-loader’,

options: {

sourceMap: false

}

}

]

}

]

},

/* config.module.rule(‘stylus’) */

{

test: /.styl(us)?$/,

oneOf: [

/* config.module.rule(‘stylus’).oneOf(‘vue-modules’) */

{

resourceQuery: /module/,

use: [

/* config.module.rule(‘stylus’).oneOf(‘vue-modules’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘stylus’).oneOf(‘vue-modules’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2,

modules: {

localIdentName: ‘[name][local][hash:base64:5]’

}

}

},

/* config.module.rule(‘stylus’).oneOf(‘vue-modules’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘stylus’).oneOf(‘vue-modules’).use(‘stylus-loader’) */

{

loader: ‘stylus-loader’,

options: {

sourceMap: false,

preferPathResolver: ‘webpack’

}

}

]

},

/* config.module.rule(‘stylus’).oneOf(‘vue’) */

{

resourceQuery: /?vue/,

use: [

/* config.module.rule(‘stylus’).oneOf(‘vue’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘stylus’).oneOf(‘vue’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2

}

},

/* config.module.rule(‘stylus’).oneOf(‘vue’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘stylus’).oneOf(‘vue’).use(‘stylus-loader’) */

{

loader: ‘stylus-loader’,

options: {

sourceMap: false,

preferPathResolver: ‘webpack’

}

}

]

},

/* config.module.rule(‘stylus’).oneOf(‘normal-modules’) */

{

test: /.module.\w+$/,

use: [

/* config.module.rule(‘stylus’).oneOf(‘normal-modules’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘stylus’).oneOf(‘normal-modules’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2,

modules: {

localIdentName: ‘[name][local][hash:base64:5]’

}

}

},

/* config.module.rule(‘stylus’).oneOf(‘normal-modules’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘stylus’).oneOf(‘normal-modules’).use(‘stylus-loader’) */

{

loader: ‘stylus-loader’,

options: {

sourceMap: false,

preferPathResolver: ‘webpack’

}

}

]

},

/* config.module.rule(‘stylus’).oneOf(‘normal’) */

{

use: [

/* config.module.rule(‘stylus’).oneOf(‘normal’).use(‘extract-css-loader’) */

{

loader: ‘//node_modules/mini-css-extract-plugin/dist/loader.js’,

options: {

hmr: false,

publicPath: ‘…/’

}

},

/* config.module.rule(‘stylus’).oneOf(‘normal’).use(‘css-loader’) */

{

loader: ‘//node_modules/css-loader/dist/cjs.js’,

options: {

sourceMap: false,

importLoaders: 2

}

},

/* config.module.rule(‘stylus’).oneOf(‘normal’).use(‘postcss-loader’) */

{

loader: ‘//node_modules/postcss-loader/src/index.js’,

options: {

sourceMap: false,

plugins: [

function () { /* omitted long function */

}

]

}

},

/* config.module.rule(‘stylus’).oneOf(‘normal’).use(‘stylus-loader’) */

{

loader: ‘stylus-loader’,

options: {

sourceMap: false,

preferPathResolver: ‘webpack’

}

}

]

}

]

},

/* config.module.rule(‘js’) */

{

test: /.m?jsx?$/,

exclude: [

function () { /* omitted long function */

}

],

use: [

/* config.module.rule(‘js’).use(‘cache-loader’) */

{

loader: ‘//node_modules/cache-loader/dist/cjs.js’,

options: {

cacheDirectory: ‘//node_modules/.cache/babel-loader’,

cacheIdentifier: ‘bf6c8644’

}

},

/* config.module.rule(‘js’).use(‘thread-loader’) */

{

// 多线程打包

loader: ‘//node_modules/thread-loader/dist/cjs.js’

},

/* config.module.rule(‘js’).use(‘babel-loader’) */

{

loader: ‘//node_modules/babel-loader/lib/index.js’

}

]

},

/* config.module.rule(‘eslint’) */

{

enforce: ‘pre’,

test: /.(vue|(j|t)sx?)$/,

exclude: [

/node_modules/,

‘//node_modules/@vue/cli-service/lib’

],

use: [

/* config.module.rule(‘eslint’).use(‘eslint-loader’) */

{

loader: ‘//node_modules/eslint-loader/index.js’,

options: {

extensions: [

‘.js’,

‘.jsx’,

‘.vue’

],

cache: true,

cacheIdentifier: ‘6340a568’,

emitWarning: false,

emitError: false,

eslintPath: ‘//node_modules/eslint’,

formatter: undefined

}

}

]

}

]

},

optimization: {

splitChunks: {

cacheGroups: {

vendors: {

name: ‘chunk-vendors’,

test: /[\/]node_modules[\/]/,

priority: -10,

chunks: ‘initial’

},

common: {

name: ‘chunk-common’,

minChunks: 2,

priority: -20,

chunks: ‘initial’,

reuseExistingChunk: true

}

}

},

minimizer: [

/* config.optimization.minimizer(‘terser’) */

new TerserPlugin(

{

terserOptions: {

compress: {

arrows: false,

collapse_vars: false,

comparisons: false,

computed_props: false,

hoist_funs: false,

hoist_props: false,

hoist_vars: false,

inline: false,

loops: false,

negate_iife: false,

properties: false,

reduce_funcs: false,

reduce_vars: false,

switches: false,

toplevel: false,

typeofs: false,

booleans: true,

if_return: true,

sequences: true,

unused: true,

conditionals: true,

dead_code: true,

evaluate: true

},

mangle: {

safari10: true

}

},

sourceMap: true,

cache: true,

parallel: true,

extractComments: false

}

)

]

},

plugins: [

/* config.plugin(‘vue-loader’) */

new VueLoaderPlugin(),

/* config.plugin(‘define’) */

new DefinePlugin(

{

‘process.env’: {

NODE_ENV: ‘“production”’,

BASE_URL: ‘“/”’

}

}

),

/* config.plugin(‘case-sensitive-paths’) */

new CaseSensitivePathsPlugin(),

/* config.plugin(‘friendly-errors’) */

new FriendlyErrorsWebpackPlugin(

{

additionalTransformers: [

function () { /* omitted long function */

}

],

additionalFormatters: [

function () { /* omitted long function */

}

]

}

),

/* config.plugin(‘extract-css’) */

new MiniCssExtractPlugin(

{

filename: ‘css/[name].[contenthash:8].css’,

chunkFilename: ‘css/[name].[contenthash:8].css’

}

),

/* config.plugin(‘optimize-css’) */

new OptimizeCssnanoPlugin(

{

sourceMap: false,

cssnanoOptions: {

preset: [

‘default’,

{

mergeLonghand: false,

cssDeclarationSorter: false

}

]

}

}

),

/* config.plugin(‘hash-module-ids’) */

new HashedModuleIdsPlugin(

{

hashDigest: ‘hex’

}

),

/* config.plugin(‘named-chunks’) */

new NamedChunksPlugin(

function () { /* omitted long function */

}

),

/* config.plugin(‘html’) */

new HtmlWebpackPlugin(

{

title: ‘02.vue_cli’,

templateParameters: function () { /* omitted long function */

},

minify: {

removeComments: true,

collapseWhitespace: true,

collapseBooleanAttributes: true,

removeScriptTypeAttributes: true

},

template: ‘//public/index.html’

}

),

/* config.plugin(‘preload’) */

new PreloadPlugin(

{

rel: ‘preload’,

include: ‘initial’,

fileBlacklist: [

/.map$/,

/hot-update.js$/

]

}

),

/* config.plugin(‘prefetch’) */

new PreloadPlugin(

{

rel: ‘prefetch’,

include: ‘asyncChunks’

}

),

/* config.plugin(‘copy’) */

new CopyPlugin(

[

{

from: ‘//public’,

to: ‘//dist’,

toType: ‘dir’,

ignore: [

‘.DS_Store’,

{

glob: ‘index.html’,

matchBase: false

}

]

}

]

)

],

entry: {

app: [

‘./src/main.js’

]

}

}

比较

生产环境css相关loader有些变化,js进行多线程打包,加了一些插件

loader


loader本质上是函数,webpack在调用的时候会将文件传递到函数中,函数处理完成后将结果返回

即:loader是对文件做处理的函数

如果用use指定使用多个loader,那么loader的执行顺序是从下向上(从右向左/从后向前)。

但是loader中可以指定pitch函数,pitch会从前向后执行

module.exports.pitch = function () {

xxx

}

即:在loader中,module.exports函数,会从后向前依次执行,但是module.exports.pitch函数,会从前向后执行

// loader本质上是一个函数

// 同步loader

// module.exports = function (content, map, meta) {

// console.log(111);

// return content;

// }

module.exports = function (content, map, meta) {

console.log(111);

this.callback(null, content, map, meta);

}

module.exports.pitch = function () {

console.log(‘pitch 111’);

}

loader可以使用异步loader,使用this.async(),并使用callback接收。后续可以做一些异步操作,做完后执行callback才会执行后续操作。

// loader本质上是一个函数

// 异步loader

module.exports = function (content, map, meta) {

console.log(222);

const callback = this.async();

setTimeout(() => {

callback(null, content);

}, 1000)

}

module.exports.pitch = function () {

console.log(‘pitch 222’);

}

在使用loader的时候,会使用options传递一些参数

{

loader: ‘loader3’,

options: {

name: ‘jack’,

age: 18

}

}

可以使用loader-utils库进行接收参数

使用方法

// loader本质上是一个函数

const { getOptions } = require(‘loader-utils’);

module.exports = function (content, map, meta) {

// 获取options

const options = getOptions(this);

console.log(333, options);

return content;

}

module.exports.pitch = function () {

console.log(‘pitch 333’);

}

可以使用schema-utils库进行参数校验

使用方法:

  1. 定义schema.json确定格式,确定格式描述是否允许追加等信息

{

“type”: “object”,

“properties”: {

“name”: {

“type”: “string”,

“description”: “名称~”

}

},

“additionalProperties”: false

}

其中additionalProperties表示是否可以追加其他属性

在这里插入图片描述

  1. 在loader中进行校验

// loader本质上是一个函数

const {getOptions} = require(‘loader-utils’);

const {validate} = require(‘schema-utils’);

const schema = require(‘./schema’);

module.exports = function (content, map, meta) {

// 获取options

const options = getOptions(this);

console.log(333, options);

// 校验options是否合法

validate(schema, options, {

name: ‘loader3’

})

return content;

}

module.exports.pitch = function () {

console.log(‘pitch 333’);

}

validate接收三个参数,第一个是校验规则,第二个是参数,第三个指定当前loader名称。

自定义babelLaoder

  1. 定义校验规则

babelSchema.json

{

“type”: “object”,

“properties”: {

“presets”: {

“type”: “array”

}

},

“additionalProperties”: true

}

  1. 定义babelLoader

const { getOptions } = require(‘loader-utils’);

const { validate } = require(‘schema-utils’);

const babel = require(‘@babel/core’);

const util = require(‘util’);

const babelSchema = require(‘./babelSchema.json’);

// babel.transform用来编译代码的方法

// 是一个普通异步方法

// util.promisify将普通异步方法转化成基于promise的异步方法

const transform = util.promisify(babel.transform);

module.exports = function (content, map, meta) {

// 获取loader的options配置

const options = getOptions(this) || {};

// 校验babel的options的配置

validate(babelSchema, options, {

name: ‘Babel Loader’

});

// 创建异步

const callback = this.async();

// 使用babel编译代码

transform(content, options)

.then(({code, map}) => callback(null, code, map, meta))

.catch((e) => callback(e))

}

plugins


Tapable

Webpack 核心模块 tapable 解析(转)

const {SyncHook, SyncBailHook, AsyncParallelHook, AsyncSeriesHook} = require(‘tapable’);

class Lesson {

constructor() {

// 初始化hooks容器

this.hooks = {

// 同步hooks,任务回依次执行

// go: new SyncHook([‘address’])

// SyncBailHook:一旦有返回值就会退出~

go: new SyncBailHook([‘address’]),

// 异步hooks

// AsyncParallelHook:异步并行

// leave: new AsyncParallelHook([‘name’, ‘age’]),

// AsyncSeriesHook: 异步串行

leave: new AsyncSeriesHook([‘name’, ‘age’])

}

}

tap() {

// 往hooks容器中注册事件/添加回调函数

this.hooks.go.tap(‘class0318’, (address) => {

console.log(‘class0318’, address);

return 111;

})

this.hooks.go.tap(‘class0410’, (address) => {

console.log(‘class0410’, address);

})

this.hooks.leave.tapAsync(‘class0510’, (name, age, cb) => {

setTimeout(() => {

console.log(‘class0510’, name, age);

cb();

}, 2000)

})

this.hooks.leave.tapPromise(‘class0610’, (name, age) => {

return new Promise((resolve) => {

setTimeout(() => {

console.log(‘class0610’, name, age);

resolve();

}, 1000)

})

})

}

start() {

// 触发hooks

this.hooks.go.call(‘c318’);

this.hooks.leave.callAsync(‘jack’, 18, function () {

// 代表所有leave容器中的函数触发完了,才触发

console.log(‘end~~~’);

});

}

}

const l = new Lesson();

l.tap();

l.start();

每一个plugin调用的时候都是通过new进行调用的,所以每一个plugin都是一个构造函数或者类。

每一个插件类中必须有一个apply函数,因为插件是通过这个函数进行调用的,接受compiler参数

插件就是在webpack不同生命周期内执行不同操作

class Plugin1 {

apply(complier) {

complier.hooks.emit.tap(‘Plugin1’, (compilation) => {

console.log(‘emit.tap 111’);

})

complier.hooks.emit.tapAsync(‘Plugin1’, (compilation, cb) => {

setTimeout(() => {

console.log(‘emit.tapAsync 111’);

cb();

}, 1000)

})

complier.hooks.emit.tapPromise(‘Plugin1’, (compilation) => {

return new Promise((resolve) => {

setTimeout(() => {

console.log(‘emit.tapPromise 111’);

resolve();

}, 1000)

})

})

complier.hooks.afterEmit.tap(‘Plugin1’, (compilation) => {

console.log(‘afterEmit.tap 111’);

})

complier.hooks.done.tap(‘Plugin1’, (stats) => {

console.log(‘done.tap 111’);

})

}

}

module.exports = Plugin1;

node环境中调试

package.json中添加

“scripts”: {

“start”: “node --inspect-brk ./node_modules/webpack/bin/webpack.js”

}

表示以调试的方式启动,并在第一行打断点。调试webpack.js文件。

  1. 在需要 调试的地方打debugger断点

  2. 通过node运行文件

  3. 网页中启动

const fs = require(‘fs’);

const util = requ33333333333333333333333333333333333333333333333333333ire(‘util’);

const path = require(‘path’);

const webpack = require(‘webpack’);

const { RawSource } = webpack.sources;

// 将fs。readFile方法变成基于promise风格的异步方法

const readFile = util.promisify(fs.readFile);

class Plugin2 {

apply(compiler) {

// 初始化compilation钩子

compiler.hooks.thisCompilation.tap(‘Plugin2’, (compilation) => {

// debugger

// console.log(compilation);

// 添加资源

compilation.hooks.additionalAssets.tapAsync(‘Plugin2’, async (cb) => {

// debugger

// console.log(compilation);

const content = ‘hello plugin2’;

// 往要输出资源中,添加一个a.txt

compilation.assets[‘a.txt’] = {

// 文件大小

size() {

return content.length;

},

// 文件内容

source() {

return content;

}

}

const data = await readFile(path.resolve(__dirname, ‘b.txt’));

// compilation.assets[‘b.txt’] = new RawSource(data);

compilation.emitAsset(‘b.txt’, new RawSource(data));

cb();

})

})

}

}

module.exports = Plugin2;

自定义plugin

schema.json

{

“type”: “object”,

“properties”: {

“from”: {

“type”: “string”

},

“to”: {

“type”: “string”

},

“ignore”: {

“type”: “array”

}

},

“additionalProperties”: false

}

CopyWebpackPlugin.js

const path = require(‘path’);

const fs = require(‘fs’);

const {promisify} = require(‘util’)

const {validate} = require(‘schema-utils’);

const globby = require(‘globby’);

const webpack = require(‘webpack’);

const schema = require(‘./schema.json’);

const {Compilation} = require(‘webpack’);

const readFile = promisify(fs.readFile);

const {RawSource} = webpack.sources

class CopyWebpackPlugin {

constructor(options = {}) {

// 验证options是否符合规范

validate(schema, options, {

name: ‘CopyWebpackPlugin’

})

this.options = options;

}

apply(compiler) {

// 初始化compilation

compiler.hooks.thisCompilation.tap(‘CopyWebpackPlugin’, (compilation) => {

// 添加资源的hooks

compilation.hooks.additionalAssets.tapAsync(‘CopyWebpackPlugin’, async (cb) => {

// 将from中的资源复制到to中,输出出去

const {from, ignore} = this.options;

const to = this.options.to ? this.options.to : ‘.’;

// context就是webpack配置

// 运行指令的目录

const context = compiler.options.context; // process.cwd()

// 将输入路径变成绝对路径

const absoluteFrom = path.isAbsolute(from) ? from : path.resolve(context, from);

// 1. 过滤掉ignore的文件

// globby(要处理的文件夹,options)

const paths = await globby(absoluteFrom, {ignore});

console.log(paths); // 所有要加载的文件路径数组

// 2. 读取paths中所有资源

const files = await Promise.all(

paths.map(async (absolutePath) => {

// 读取文件

const data = await readFile(absolutePath);

// basename得到最后的文件名称

const relativePath = path.basename(absolutePath);

// 和to属性结合

// 没有to --> reset.css

// 有to --> css/reset.css

const filename = path.join(to, relativePath);

return {

// 文件数据

data,

// 文件名称

filename

}

})

)

// 3. 生成webpack格式的资源

const assets = files.map((file) => {

const source = new RawSource(file.data);

return {

source,

filename: file.filename

}

})

// 4. 添加compilation中,输出出去

assets.forEach((asset) => {

compilation.emitAsset(asset.filename, asset.source);

})

cb();

})

})

}

}

module.exports = CopyWebpackPlugin;

webpack.config.js中使用

const CopyWebpackPlugin = require(‘./plugins/CopyWebpackPlugin’)

module.exports = {

plugins: [

new CopyWebpackPlugin({

from: ‘public’,

to: ‘css’,

ignore: [‘**/index.html’]

})

]

}

webpack执行流程


  1. 初始化Complier:new Webpack(config)得到Complier对象

  2. 开始编译:调用Compiler对象run方法开始执行编译

  3. 确定入口:根据配置中的entry找出所有的入口文件

  4. 编译模块:从入口文件出发,调用所有配置的loader对模块进行编译,再找出该模块依赖的模块,递归直到所有的模块都被加载进来

  5. 完成模块编译:经过第4步使用Loader编译完所有模块后,得到每个模块被编译后的最终内容以及它们之间的依赖关系

  6. 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的Chunk,再把每个Chunk转换成一个单独的文件加入到输出列表。(注意:这步是可以修改输出内容的最后机会)

  7. 输出完成:在确定好输出内容后,根据配置正确输出的路径和文件名,把文件内容写入到文件系统

自定义myWebpack


文件 目录

在这里插入图片描述

config/webpack.config.js

const path = require(‘path’);

module.exports = {

entry: ‘./src/index.js’,

output: {

path: path.resolve(__dirname, ‘…/dist’),

filename: ‘main.js’

}

}

dist/index.html

webpack

dist/main.js

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

img
img

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V:vip1024c 备注前端获取(资料价值较高,非无偿)
img

总结一下

面试前要精心做好准备,简历上写的知识点和原理都需要准备好,项目上多想想难点和亮点,这是面试时能和别人不一样的地方。

还有就是表现出自己的谦虚好学,以及对于未来持续进阶的规划,企业招人更偏爱稳定的人。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

万事开头难,但是程序员这一条路坚持几年后发展空间还是非常大的,一切重在坚持。

为了帮助大家更好更高效的准备面试,特别整理了《前端工程师面试手册》电子稿文件。

前端面试题汇总

JavaScript

性能

linux

前端资料汇总

前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。

.join(to, relativePath);

return {

// 文件数据

data,

// 文件名称

filename

}

})

)

// 3. 生成webpack格式的资源

const assets = files.map((file) => {

const source = new RawSource(file.data);

return {

source,

filename: file.filename

}

})

// 4. 添加compilation中,输出出去

assets.forEach((asset) => {

compilation.emitAsset(asset.filename, asset.source);

})

cb();

})

})

}

}

module.exports = CopyWebpackPlugin;

webpack.config.js中使用

const CopyWebpackPlugin = require(‘./plugins/CopyWebpackPlugin’)

module.exports = {

plugins: [

new CopyWebpackPlugin({

from: ‘public’,

to: ‘css’,

ignore: [‘**/index.html’]

})

]

}

webpack执行流程


  1. 初始化Complier:new Webpack(config)得到Complier对象

  2. 开始编译:调用Compiler对象run方法开始执行编译

  3. 确定入口:根据配置中的entry找出所有的入口文件

  4. 编译模块:从入口文件出发,调用所有配置的loader对模块进行编译,再找出该模块依赖的模块,递归直到所有的模块都被加载进来

  5. 完成模块编译:经过第4步使用Loader编译完所有模块后,得到每个模块被编译后的最终内容以及它们之间的依赖关系

  6. 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的Chunk,再把每个Chunk转换成一个单独的文件加入到输出列表。(注意:这步是可以修改输出内容的最后机会)

  7. 输出完成:在确定好输出内容后,根据配置正确输出的路径和文件名,把文件内容写入到文件系统

自定义myWebpack


文件 目录

在这里插入图片描述

config/webpack.config.js

const path = require(‘path’);

module.exports = {

entry: ‘./src/index.js’,

output: {

path: path.resolve(__dirname, ‘…/dist’),

filename: ‘main.js’

}

}

dist/index.html

webpack

dist/main.js

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-A2hZg9EO-1711589644111)]
[外链图片转存中…(img-stShDgAQ-1711589644112)]
[外链图片转存中…(img-w3xFdyUh-1711589644112)]
[外链图片转存中…(img-ZB0lWHgv-1711589644112)]
[外链图片转存中…(img-aTQW7reh-1711589644113)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

[外链图片转存中…(img-RRrtBpgM-1711589644113)]
[外链图片转存中…(img-1IwJjM0x-1711589644113)]

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V:vip1024c 备注前端获取(资料价值较高,非无偿)
[外链图片转存中…(img-8EhfXlKs-1711589644114)]

总结一下

面试前要精心做好准备,简历上写的知识点和原理都需要准备好,项目上多想想难点和亮点,这是面试时能和别人不一样的地方。

还有就是表现出自己的谦虚好学,以及对于未来持续进阶的规划,企业招人更偏爱稳定的人。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

万事开头难,但是程序员这一条路坚持几年后发展空间还是非常大的,一切重在坚持。

为了帮助大家更好更高效的准备面试,特别整理了《前端工程师面试手册》电子稿文件。

前端面试题汇总

JavaScript

性能

linux

前端资料汇总

前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。

  • 18
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值