我尝试使用动态导入将服务器生成的config.js
文件插入到我们应用的生产版本中。
我试图以这种方式使用它:
import('./config').then(function(config){
//create a global config variable
config = config;
})
(暂时)
当我运行webpack
时,我收到以下错误
Module build failed: SyntaxError: Unexpected token, expected { (1:6)
Research让我相信这与babel-loader
有关,或许与动态导入效果不佳,但我认为已经解决了#34;有更新的版本。
解决方案似乎可能是安装Syntax Dynamic Import或babel-plugin-dynamic-import-node,但我不清楚哪一个或为什么。
package.json 的相关位:
{
"name": "app",
"version": "0.0.1",
"private": true,
"scripts": {
"build": "node config/webpack/build.js",
},
"dependencies": {
"amdi18n-loader": "^0.6.2",
"async": "^2.6.0",
"babel-core": "^6.26.0",
"babel-eslint": "^8.2.2",
"babel-loader": "^7.1.4",
"babel-plugin-istanbul": "^4.1.6",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.1",
"babel-preset-stage-2": "^6.24.1",
"babel-register": "^6.26.0",
"chalk": "^2.3.0",
"css-loader": "^0.28.10",
"file-loader": "^1.1.6",
"html-webpack-plugin": "^3.2.0",
"less": "^3.0.1",
"less-loader": "^4.0.6",
"promise-polyfill": "^7.1.0",
"raw-loader": "^0.5.1",
"style-loader": "^0.20.2",
"webpack": "^4.5.0"
},
"devDependencies": {
"autoprefixer": "^7.2.3",
"chromedriver": "^2.34.0",
"copy-webpack-plugin": "^4.3.0",
"cross-env": "^5.1.1",
"cross-spawn": "^5.1.0",
"eslint": "^4.13.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.9.0",
"eslint-plugin-html": "^4.0.1",
"friendly-errors-webpack-plugin": "^1.6.1",
"inject-loader": "^3.0.1",
"madge": "^2.0.0",
"node-notifier": "^5.1.2",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.9",
"rimraf": "^2.6.2",
"semver": "^5.4.1",
"shelljs": "^0.7.8",
"source-map-support": "*",
"uglifyjs-webpack-plugin": "^1.1.4",
"url-loader": "^0.6.2",
"uuid": "^3.1.0",
"webpack-bundle-analyzer": "^2.9.1",
"webpack-cli": "^2.0.14",
"webpack-dev-server": "^3.1.3",
"webpack-merge": "^4.1.1"
},
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
}
}
我们将webpack.conf.js拆分为 webpack.base.conf
'use strict';
const path = require('path');
const utils = require('./utils');
const config = require('../');
function resolve(dir) {
return path.join(__dirname, '../..', dir);
}
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
});
module.exports = {
context: path.resolve(__dirname, '../../'),
entry: {
app: './public/js/ide.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'all'
}
}
}
},
resolve: {
extensions: ['.js', '.json', '.less'],
alias: {
'@': resolve('public/js'),
},
modules: ['less', 'node_modules']
},
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('public/js'), resolve('test')],
exclude: [
path.resolve(__dirname, "public/js/config.js")
],
},
{
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]')
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.less$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "less-loader" // compiles Less to CSS
}]
},
{
test: /\.hbs$/,
use: ['raw-loader']
}
]
},
node: {
setImmediate: false,
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
};
...和 webpack.prod.conf.js
const webpackConfig = merge(baseWebpackConfig, {
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({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
new HtmlWebpackPlugin({
filename: process.env.NODE_ENV === 'testing'
? 'public/html/ide.html'
: config.build.index,
template: 'public/html/ide.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency'
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
new webpack.HashedModuleIdsPlugin(),
new webpack.optimize.ModuleConcatenationPlugin(),
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../../public/fonts'),
to: config.build.assetsFonts,
},
{
from: path.resolve(__dirname, '../../public/img'),
to: config.build.assetsImg,
}
])
]
});
在1中,用户表示babel-loader应该"只是工作"现在有动态导入,所以我不确定我错过了什么。有什么过时的吗?我的配置有些奇怪吗?
答案 0 :(得分:4)
您需要做几件事。
首先,与上述评论中的某些人一样,您需要为配置使用不同的变量名称。此外,如果您以这种方式使用import
,则您获得的对象是ES6导出的对象,因此您的数据将位于default
import('./config').then(function(localConfig){
//create a global config variable
config = localConfig.default;
})
接下来,您获得的错误是babel未使用正确预设的结果。你需要至少在第二阶段才能发挥作用。
{
test: /\.js$/,
loader: 'babel-loader',
options: {
presets: ['es2015','stage-2']
}
include: [resolve('public/js'), resolve('test')],
exclude: [
path.resolve(__dirname, "public/js/config.js")
],
},
这将解决您的错误,但仍然不是您想要的。现在发生的一切是webpack将你的配置文件拆分成它自己的块,在运行时发出一个新的http请求来获取这个文件。但它不会使用服务器上的配置文件,而是使用构建中生成的块
要在运行时加载服务器上的实际配置,您需要在应用程序中发出正常的http请求
这是一个很好的stackoverflow答案。
https://stackoverflow.com/a/36725115/9083959